text:
8bit virtual machine
Background
I like my old 8-bit 6502 chip. It's even fun to solve some of the challenges here on PPCG in 6502 machine code. But some things that should be simple (like, read in data or output to stdout) are unnecessarily cumbersome to do in machine code. So there's a rough idea in my mind: Invent my own 8-bit virtual machine that's inspired by the 6502, but with the design modified to be more usable for challenges. Starting to implement something, I realized this might be a nice challenge itself if the design of the VM is reduced to a bare minimum :)
Task
Implement an 8-bit virtual machine conforming to the following specification. This is code-golf, so the implementation with the fewest bytes wins.
Input
Your implementation should take the following inputs:

A single unsigned byte pc, this is the initial program counter (the address in memory where the VM starts execution, 0-based)

A list of bytes with a maximum length of 256 entries, this is the RAM for the virtual machine (with its initial contents)

You may take this input in any sensible format.
Output
A list of bytes which are the final contents of the RAM after the VM terminates (see below). You can assume you only get input that leads to terminating eventually. Any sensible format is allowed.
Virtual CPU
The virtual CPU has

an 8-bit program counter,
an 8-bit accumulator register called A and
an 8-bit index register called X.

There are three status flags:

Z - the zero flag is set after some operation results in 0
N - the negative flag is set after some operation results in a negative number (iow bit 7 of the result is set)
C - the carry flag is set by additions and shifts for the "missing" bit of the result

Upon start, the flags are all cleared, the program counter is set to a given value and the contents of A and X are indeterminate.
The 8-bit values represent either

an unsigned integer in the range [0..255]
a signed integer, 2's complement, in the range [-128..127]

depending on context. If an operation over- or underflows, the value wraps around (and in case of an addition, the carry flag is affected).
Termination
The virtual machine terminates when

A HLT instruction is reached
A non-existing memory address is accessed
The program counter runs outside the memory (note it doesn't wrap around even if the VM is given the full 256 bytes of memory)

Adressing modes

implicit -- the instruction has no argument, the operand is implied
immediate -- the operand is the byte directly after the instruction
relative -- (for branching only) the byte after the instruction is signed (2's complement) and determines the offset to add to the program counter if the branch is taken. 0 is the location of the following instruction
absolute -- the byte after the instruction is the address of the operand
indexed -- the byte after the instruction plus X (the register) is the address of the operand

Instructions
Each instruction consists of an opcode (one byte) and, in the addressing modes immediate, relative, absolute and indexed a second argument byte. When the virtual CPU executes an instruction, it increments the program counter accordingly (by 1 or 2).
All opcodes shown here are in hex.

LDA -- load operand into A

Opcodes: immediate: 00, absolute: 02, indexed: 04
Flags: Z, N

STA -- store A into operand

Opcodes: immediate: 08, absolute: 0a, indexed: 0c

LDX -- load operand into X

Opcodes: immediate: 10, absolute: 12, indexed: 14
Flags: Z, N

STX -- store X into operand

Opcodes: immediate: 18, absolute: 1a, indexed: 1c

AND -- bitwise and of A and operand into A

Opcodes: immediate: 30, absolute: 32, indexed: 34
Flags: Z, N

ORA -- bitwise or of A and operand into A

Opcodes: immediate: 38, absolute: 3a, indexed: 3c
Flags: Z, N

EOR -- bitwise xor (exclusive or) of A and operand into A

Opcodes: immediate: 40, absolute: 42, indexed: 44
Flags: Z, N

LSR -- logical shift right, shift all bits of operand one place to the right, bit 0 goes to carry

Opcodes: immediate: 48, absolute: 4a, indexed: 4c
Flags: Z, N, C

ASL -- arithmetic shift left, shift all bits of the operand one place to the left, bit 7 goes to carry

Opcodes: immediate: 50, absolute: 52, indexed: 54
Flags: Z, N, C

ROR -- rotate right, shift all bits of operand one place to the right, carry goes to bit 7, bit 0 goes to carry

Opcodes: immediate: 58, absolute: 5a, indexed: 5c
Flags: Z, N, C

ROL -- rotate left, shift all bits of the operand one place to the left, carry goes to bit 0, bit 7 goes to carry

Opcodes: immediate: 60, absolute: 62, indexed: 64
Flags: Z, N, C

ADC -- add with carry, operand plus carry is added to A, carry is set on overflow

Opcodes: immediate: 68, absolute: 6a, indexed: 6c
Flags: Z, N, C

INC -- increment operand by one

Opcodes: immediate: 78, absolute: 7a, indexed: 7c
Flags: Z, N

DEC -- decrement operand by one

Opcodes: immediate: 80, absolute: 82, indexed: 84
Flags: Z, N

CMP -- compare A with operand by subtracting operand from A, forget result. Carry is cleared on underflow, set otherwise

Opcodes: immediate: 88, absolute: 8a, indexed: 8c
Flags: Z, N, C

CPX -- compare X -- same as CMP for X

Opcodes: immediate: 90, absolute: 92, indexed: 94
Flags: Z, N, C

HLT -- terminate

Opcodes: implicit: c0

INX -- increment X by one

Opcodes: implicit: c8
Flags: Z, N

DEX -- decrement X by one

Opcodes: implicit: c9
Flags: Z, N

SEC -- set carry flag

Opcodes: implicit: d0
Flags: C

CLC -- clear carry flag

Opcodes: implicit: d1
Flags: C

BRA -- branch always

Opcodes: relative: f2

BNE -- branch if Z flag cleared

Opcodes: relative: f4

BEQ -- branch if Z flag set

Opcodes: relative: f6

BPL -- branch if N flag cleared

Opcodes: relative: f8

BMI -- branch if N flag set

Opcodes: relative: fa

BCC -- branch if C flag cleared

Opcodes: relative: fc

BCS -- branch if C flag set

Opcodes: relative: fe

Opcodes
The behavior of the VM is undefined if any opcode is found that doesn't map to a valid instruction from the above list.
As per Jonathan Allan's request, you may choose your own set of opcodes instead of the opcodes shown in the Instructions section. If you do so, you must add a full mapping to the opcodes used above in your answer.
The mapping should be a hex file with pairs <official opcode> <your opcode>, e.g. if you replaced two opcodes:
f4 f5
10 11

Newlines don't matter here.
Test cases (official opcodes)
// some increments and decrements
pc:     0
ram:    10 10 7a 01 c9 f4 fb
output: 10 20 7a 01 c9 f4 fb

// a 16bit addition
pc:     4
ram:    e0 08 2a 02 02 00 6a 02 0a 00 02 01 6a 03 0a 01
output: 0a 0b 2a 02 02 00 6a 02 0a 00 02 01 6a 03 0a 01

// a 16bit multiplication
pc:     4
ram:    5e 01 28 00 10 10 4a 01 5a 00 fc 0d 02 02 d1 6a 21 0a 21 02 03 6a 22 0a 22 52
        02 62 03 c9 f8 e6 c0 00 00
output: 00 00 00 00 10 10 4a 01 5a 00 fc 0d 02 02 d1 6a 21 0a 21 02 03 6a 22 0a 22 52
        02 62 03 c9 f8 e6 c0 b0 36

I might add more testcases later.
Reference and testing
To help with own experiments, here's some (totally not golfed) reference implementation -- it can output tracing information (including disassembled instructions) to stderr and convert opcodes while running.
Recommended way to get the source:
git clone https://github.com/zirias/gvm --branch challenge --single-branch --recurse-submodules

Or checkout branch challenge and do a git submodule update --init --recursive after cloning, to get my custom build system.
Build the tool with GNU make (just type make, or gmake if on your system, the default make isn't GNU make).
Usage: gvm [-s startpc] [-h] [-t] [-c convfile] [-d] [-x] <initial_ram

-s startpc -- the initial program counter, defaults to 0
-h -- input is in hex (otherwise binary)
-t -- trace execution to stderr
-c convfile -- convert opcodes according to a mapping given in convfile
-d -- dump resulting memory as binary data
-x -- dump resulting memory as hex
initial_ram -- the initial RAM contents, either hex or binary

Note the conversion feature will fail on programs that modify opcodes while running.
Disclaimer: The rules and specs above are authorative for the challenge, not this tool. This especially applies to the opcode conversion feature. If you think the tool presented here has a bug wrt the specs, please report in a comment :)

I'd imagine that there would probably be numerous golfing opportunities to be had by choosing different opcodes for the instructions but it seems the opcodes have been fixed (even though the instruction set is what defines the machine). Maybe it's worth considering allowing implementations to have their own code-page?

@JonathanAllan thought twice about it, I'm allowing it now and might add a "conversion" tool to make solutions using other sets of opcodes easily testable.

Related.

@PeterTaylor only very loosely -- I've seen this one ;) my instruction set is inspired by the 6502, but the architecture here is greatly simplified, so golfed solutions are (hopefully) realistic ;)

Adding the link in comments causes both questions to show up in the other's "Linked" sidebar, so in particular people who find the other question by some means will be slightly more likely to then find this one and answer it.

@PeterTaylor I didn't oppose mentioning it ;) just wanted to emphasize the relation is "weak" ... it's there because the instruction set here is inspired by the famous 6502 :)

What's the expected behavior of STA, STX, DEC, etc. with immediate addressing? Self-modifying code?

@Arnauld yes, straight forward -- they modify their operand, so if the operand is immediate, that byte is modified :) (this would allow for very strange code, but with the liberty to choose your own opcodes, I can't use it in testcases ....)

@Arnauld btw my reasoning for allowing this was to reduce the amount of special cases, so it should be better "golfable" -- each opcode is either implicit, a relative branch or allows all three other addressing modes :)

if BRA ("branch always") doesn't introduce a branch in the control flow, shouldn't it be called JMP?

@ngn well, BRA exists in later chip designs (the 6502 doesn't have such an instruction) like the 65C02 and the MC 68000. JMP exists as well. The difference is that BRA uses relative addressing and JMP uses absolute addressing. So, I just followed these designs -- indeed, it doesn't sound all that logical ;)

Since A and X are "indeterminate" at the start, does this mean we can assume the PC will not reach a command which reads either of them before it reaches one that has set them properly?

Also, does the length of the inputted RAM represent the size of the whole RAM, or should we somehow pad it to 256 bytes?

@EriktheOutgolfer a) not for a program with a defined result (iow not for any testcase I might add), yes ;) b) the input is the RAM, so yes, with an input of size 64, 64 would be a non-existent address.

@FelixPalmen Alright, so I won't have to handle such edge-cases or pad the RAM, just making sure I've understood the challenge correctly, thanks.

a) How can ADC, INC, INX affect the N flag? Is that for simplicity of the VM? b) Do the increments and decrements wrap or what else will happen on overflow/underflow? c) Why is there no SBC?

@Titus a) what's special about those? as described, N is set whenever a result is "negative" (has bit 7 set). b) yes they do, there's not much else that would make sense, but maybe should be made explicit in the specs c) simplicity for the golfing challenge. subtraction can be done by eor #$ff, adc anyways (with inverted meaning of the carry flag).

@FelixPalmen a) I think I´ve been working with 32 and 64 bit integers for too long. Memories of the 6510 and 8bit values are a bit blurred. c) how about a IVC (invert carry) instruction then? (j/k)

@Titus the funny thing is sbc on the 6502 indeed works with an inverted carry flag. I guess this is exactly because with 2's complement, it allows to reuse the adc logic by inverting the operand :)

Also, can the C flag be set when the operand over/underflows after an INC, INX, DEC or DEX?

@Rogem no, these don't affect C.

What does LSR IMM 8 mean?

@l4m2: If I understand you correctly, see Arnauld's comment and my following comments

C (gcc), 1381 1338 1255 1073 bytes
Huge improvement thanks to ceilingcat and Rogem.
#include<stdio.h>
C*F="%02hhx ";m[256],p,a,x,z,n,c,e;g;*I(){R++p+m;}*A(){R*I()+m;}*X(){R*I()+m+x;}C*Q(){W(printf,m[g],1)exit(a);}C*(*L[])()={I,Q,A,Q,X,Q,Q,Q};l(C*i){R 254/p?*i=*L[m[p]&7]():*Q();}s(i){R 254/p?*L[m[p]&7]()=i:*Q();}q(){p>254?Q():++p;}C*y(){p+=e;}B(U,z)B(V,!z)B(_,n)B(BM,!n)B(BC,c)B(BS,!c)C*(*b[])()={Q,Q,y,Q,U,Q,V,Q,_,Q,BM,Q,BC,Q,BS,Q};j(){z=!l(&a);v}o(){s(a);}t(){z=!l(&x);n=x&H;}D(){s(x);}f(K(&=)h(K(|=)i(K(^=)J(E;c=e&1;z=!(e/=2);s(e);w}k(E;c=w;z=!e;s(e*=2);}T(E;g=e&1;z=!(e=e/2|H*!!c);c=g;s(e);w}M(E;g=w z=!(e=e*2|H*!!c);c=g;s(e);}N(E;z=!(a=g=a+e+!!c);c=g>>8%2;G}P(E;z=!~e;--p;s(g=e+1);G}u(E;g=e-1;z=!g;--p;s(g);G}r(E;g=a-e;z=!g;c=G}S(E;g=x-e;z=!g;c=G}Y(){z=!(x=g=1-m[p]%2*2);n=x&H;}Z(){c=~m[p]&1;}d(){p<255||Q();e=m[++p];b[m[p-1]&15]();}(*O[])()={j,o,t,D,Q,Q,f,h,i,J,k,T,M,N,Q,P,u,r,S,Q,Q,Q,Q,Q,Q,Y,Z,Q,Q,Q,d,d};main(){scanf(F,&p);W(scanf,&m[g],0)for(;;q())O[m[p]/8]();}

Try it online!
A lot of defines moved to compiler flags.
Explanation (VERY ungolfed):
#include<stdio.h>

// useful defines
#define C unsigned char
#define H 128 // highest bit
#define R return

// code generator for I/O
#define W(o,p,q)for(g=-1;++g<256&&((q)||!feof(stdin));)(o)(F,(p));

// code generator for branching instruction handlers
#define BB(q)(){(q)||Y();}

// frequent pieces of code
#define NA n=a&H;
#define NE n=e&H;
#define NG n=g&H;
#define E l(&e)

// printf/scanf template
C * F = "%02hhx ";

// global state: m=memory, pax=registers, znc=flags
// e and g are for temporaries and type conversions
C m[256],p,a,x,z,n,c,e;g;

// get the pointer to a memory location:
C * I() {R &m[++p];} // immediate
C * A() {R &m[m[++p]];} // absolute
C * X() {R &m[m[++p]+x];} // indexed

// terminate the VM (and dump memory contents)
C * Q() { W(printf,m[g],1) exit(a);}

// an array of functions for accessing the memory
// They either return the pointer to memory location
// or terminate the program.
C * (*L[])()={I,Q,A,Q,X,Q,Q,Q};

// load a byte from the memory into the variable pointed by i
// terminate the program if we cannot access the address byte
l (C * i) {return 254 / p ? *i = *L[m[p]&7] () : *Q ();}

// save a byte i to the memory
// terminate the program if we cannot access the address byte
s (C i) {return 254 / p ? *L[m[p]&7]() = i : *Q ();}

// advance the instruction pointer (or fail if we fall outside the memory)
q () {p > 254 ? Q () : ++p;}

// branch
C * Y() {p += e;}

// generated functions for conditional branches
C * BN BB(z)
C * BZ BB(!z)
C * BP BB(n)
C * BM BB(!n)
C * BC BB(c)
C * BS BB(!c)

// a list of branch functions
C * (*B[])() = {Q,Q,Y,Q,BN,Q,BZ,Q,BP,Q,BM,Q,BC,Q,BS,Q};

// Instruction handling functions

OA () {z = !l (&a); NA} // lda
OB () {s (a);} // sta
OC () {z = !l (&x); n = x & H;} // ldx
OD () {s (x);} // stx
OG () {E; z = !(a &= e); NA} // and
OH () {E; z = !(a |= e); NA} // ora
OI () {E; z = !(a ^= e); NA} // eor
OJ () {E; c = e & 1; z = !(e /= 2); s (e); NE} // lsr
OK () {E; c = NE; z = !e; s (e *= 2);} // asl
OL () {E; g = e & 1; z = !(e = e / 2 | H * !!c); c = g; s (e); NE} // ror
OM () {E; g = e & H; z = !(e = e * 2 | H * !!c); c = g; s (e); NE} // rol
ON () {E; z = !(a = g = a + e + !!c); c = !!(g & 256); NG} // adc
OP () {E; z = !~e; --p; s (g = e + 1); NG} // inc
OQ () {E; g = e - 1; z = !g; --p; s (g); NG} // dec
OR () {E; g = a - e; z = !g; c = NG} // cmp
OS () {E; g = x - e; z = !g; c = NG} // cpx
OY () {z = !(x = g = ~m[p] & 1 * 2 - 1); n = x & H;} // inx/dex
OZ () {c = ~m[p] & 1;} // sec/clc
Od () {p < 255 || Q (); e = m[++p]; B[m[p-1]&15] ();} // branching

// list of opcode handlers
(*O[]) () = {OA,OB,OC,OD,Q,Q,OG,OH,OI,OJ,OK,OL,OM,ON,Q,OP,OQ,OR,OS,Q,Q,Q,Q,Q,Q,OY,OZ,Q,Q,Q,Od,Od};

// main function
main ()
{
    // read the instruction pointer
    scanf (F, &p);

    // read memory contents
    W(scanf, &m[g], 0)

    // repeatedly invoke instruction handlers until we eventually terminate
    for (;; q())
        O[m[p]/8] ();
}

Great work, instant +1, really didn't expect a C solution first :) your appending of 00 bytes might be a bit bending the rules though ... I admit I didn't try to analyze this code ... could you maybe save bytes doing I/O in binary instead of hex? Would be allowed by the rules :)

I'd like to replace the rule that illegal opcodes lead to termination by just saying the behavior of illegal opcodes is undefined ... would this hurt your answer or are you fine with that?

@FelixPalmen well, as long as termination is quite valid "undefined" behavior, it won't hurt (it opens a new possibility for golfing it down instead!)

@MaxYekhlakov by "hurt" I meant being unfair towards your solution because you maybe "spent bytes" for making sure an illegal opcode terminates the vm. I'm glad you welcome the rule change as an opportunity :) And again, congrats, I just love to see a solution in C, which is my all-time favorite programming language. It's a pity you'll rarely win a code-golf challenge in C -- nevertheless, "golfed" C is just cool :)

Could you add the flags part to post?

http://zto.me/c0a8zs some optimization

C (gcc), 487, 480, 463, 452, 447, 438 bytes
Uses this instruction mapping. The update to the instructions shaved off 9 bytes, and potentially more in the future. Returns by modifying the memory pointed to by the first argument (M). Thanks to @ceilingcat for shaving off some bytes.
Must be compiled with flags -DO=*o -DD=*d -DI(e,a,b)=if(e){a;}else{b;} -Du="unsigned char" (already included in bytes).
e(M,Z,C)u*M,C;{for(u r[2],S=0,D,O,c,t;o=C<Z?M+C++:0;){I(c=O,d=r+!(c&4),break)I(o=c&3?C<Z&&C?M+C++:0:d,o=c&2?O+c%2**r+M:o,break)t=(c/=8)&7;I(c<24&c>4&&t,t&=3;I(c&8,I(c&4,c&=S&1;S=O>>7*!(t/=2);O=t=O<<!t>>t|c<<7*t,t=O+=t%2*2-1),I(c&4,D=t=t?t&2?t&1?O^D:O|D:O&D:O,I(c&1,S=D>(t=D+=O+S%2),t=D-O;S=t>D)))S=S&1|t>>6&2|4*!t,I(c&8,C+=!(t&~-t?~t&S:t&~S)*O,I(t,S=S&6|c%2,O=D)))I(C,,Z=0)}}

Try it online!
Preprocessor
-DO=*o -DD=*d

These two provide a shorter way to dereference the pointers.
-DI(e,a,b)=if(e){a;}else{b;} -Du="unsigned char"

Reduce the number of bytes needed for if-elses and type declarations.
Code
The below is a human-readable version of the code, with the preprocessor directives expanded, and variables renamed for readability.
exec_8bit(unsigned char *ram, int ramSize, unsigned char PC)
{
  for(unsigned char reg[2], SR=0, // The registers.
                                  // reg[0] is X, reg[1] is A.
                                  // SR contains the flags.
      *dst, *op, opCode, tmp;
      // Load the next instruction as long as we haven't gone out of ram.
      op = PC < ramSize ? ram + PC++ : 0;)
  { // Check for HLT.
    if(opCode=*op)
    { // Take a pointer to the register selected by complement of bit 3.
      dst = reg+!(opCode&4);
    } else break;
    // Load operand as indicated by bits 0 and 1. Also check that we don't
    // go out of bounds and that the PC doesn't overflow.
    if(op = opCode&3 ? PC<ramSize && PC ? ram + PC++ : 0 : dst)
    {
      op = opCode&2 ? *op + opCode%2 * *reg + ram: op
    } else break;

    // Store the bits 3-5 in tmp.
    tmp = (opCode/=8) & 7;
    if(opCode<24 & opCode>4 && tmp)
    { // If not HLT, CLC, SEC or ST, enter this block.
      tmp &= 3; // We only care about bits 3&4 here.
      if(opCode&8) // Determine whether the operation is binary or unary.
      { // Unary
        if(opCode&4)
        { // Bitshift
          opCode &= SR&1; // Extract carry flag and AND it with bit 3 in opCode.
          SR=*op >> 7*!(tmp/=2);// Update carry flag.
          // Shift to left if bit 4 unset, to right if set. Inclusive-OR
          // the carry/bit 3 onto the correct end.
          *op = tmp = *op << !tmp >> tmp | opCode << 7*tmp;
        } else tmp=*o+=tmp%2*2-1;
      } else if(opCode&4) {
        // Bitwise operations and LD.
        // Ternary conditional to determine which operation.
        *dst = tmp = tmp? tmp&2? tmp&1? *op^*dst: *op|*dst: *op&*dst: *op
      } else if(opCode&1) {
        // ADC. Abuse precedence to do this in fewer bytes.
        // Updates carry flag.
        SR = *dst > (tmp = *dst += *op + SR%2);
      } else tmp=*dst-*op; SR = tmp > *dst; // Comparison.
      SR = SR&1 | tmp >> 6&2 | 4*!tmp; // Update Z and N flags, leaving C as it is.
    } else if(opCode&8) {
      // Branch.
      // tmp&~-tmp returns a truthy value when tmp has more than one bit set
      // We use this to detect the "unset" and "always" conditions.
      // Then, we bitwise-AND either ~tmp&SR or tmp&~SR to get a falsy value
      // when the condition is fulfilled. Finally, we take logical complement,
      // and multiply the resulting value (`1` or `0`) with the operand,
      // and add the result to program counter to perform the jump.
      PC += !(tmp & ~-tmp? ~tmp&SR : tmp&~SR) * *op;
    } else if (tmp) { // SEC, CLC
      SR = SR&6 | opCode % 2;
    } else {
      *op = *dst; // ST
    }
    if(!PC){ // If program counter looped around, null out ramSize to stop.
           // There's likely a bug here that will kill the program when it
           // branches back to address 0x00
      ramSize=0;
    }
  }
}

Instructions
The instructions are structured as follows:

Bits 6-7 indicate the arity of the instruction (00 Nullary, 01 Unary, 10 Binary, 11 Binary)
Bits 0-2 determine the operand(s): R=0 selects A and R=1 selects X. OP=00 uses the register as an operand, OP=01 selects immediate operand, OP=10 selects absolute operand and OP=11 selects indexed operand.

As you may have noticed, this allows for any operations to be performed on either register (although you can still only index from X) even when they normally couldn't be used per specification. E.g. INC A, ADC X, 10 and ASL X all work.

Bits 3-5 determine the condition for branching: having one of the bits indicates which flag to test (bit 3->C, bit 4->N, bit 5->Z). If only one bit is set, the instruction tests for a set flag. To test for an unset flag, take the complement of the bits. For example 110 tests for unset carry and 001 for set carry. 111 and 000 branch always.
You can also branch to an address offset stored in a register, allowing you to write functions, or you can use the standard indexing modes. OP=01 behaves like specification branch.

+-----+----------+-------+-----------------------------------------------+
| OP  | BINARY   | FLAGS | INFO                                          |
+-----+----------+-------+-----------------------------------------------+
| ST  | 10000ROP |       | Register -> Operand                           |
| LD  | 10100ROP | Z N   | Operand -> Register                           |
| AND | 10101ROP | Z N   | Register &= Operand                           |
| XOR | 10111ROP | Z N   | Register ^= Operand                           |
| IOR | 10110ROP | Z N   | Register |= Operand                           |
| ADC | 10011ROP | Z N C | Register += Operand + Carry                   |
| INC | 01011ROP | Z N   | Operand += 1                                  |
| DEC | 01010ROP | Z N   | Operand -= 1                                  |
| ASL | 01100ROP | Z N C | Operand <<= 1                                 |
| LSR | 01110ROP | Z N C | Operand >>= 1                                 |
| ROL | 01101ROP | Z N C | Operand = Operand << 1 | Carry                |
| ROR | 01111ROP | Z N C | Operand = Operand >> 1 | Carry << 7           |
| CMP | 10010ROP | Z N C | Update ZNC based on Register - Operand        |
| BR  | 11CNDROP |       | PC += Condition ? Operand : 0      |
| SEC | 00011000 |     C | Set carry                                     |
| CLC | 00010000 |     C | Clear carry                                   |
| HLT | 00000000 |       | Halt execution.                               |
+-----+----------+-------+-----------------------------------------------+

APL (Dyalog Classic), 397 332 330 bytes
thanks @Adám for -8 bytes
f←{q←2⍴a x c←≡B←256⋄{0::m
⍺←(∇q∘←)0∘=,B≤+⍨
30≤u←⌊8÷⍨b←p⊃m:∇p+←129-B|127-1⊃p↓m×⊃b⌽2/(,~,⍪)1,q,c
p+←1
u=25:⍺x⊢←B|x+¯1*b
u=26:∇c⊢←~2|b
p+←≢o←m⊃⍨i←⍎'p⊃m+x'↑⍨1+8|b
⍎u⊃(,⍉'⍺ax⊢←o' '∇m[i]←ax'∘.~'xa'),5 4 2 3 2/'⍺⌽⊃'∘,¨'a⊢←2⊥(⍕⊃u⌽''∧∨≠'')/o a⊤⍨8⍴2' 'c(i⊃m)←u⌽d⊤(⌽d←u⌽2B)⊥u⌽o,c×u>10' 'c a⊢←2B⊤a+o+c' 'm[i]←B|o-¯1*u' 'c⊢←⊃2B⊤o-⍨⊃u⌽x a'}p m←⍵}

Try it online!
p  program counter
m  memory
a  accumulator register
x  index register
q  flags z (zero) and n (negative) as a length-2 vector
c  flag for carry
⍺  function to update z and n
b  current instruction
u  highest 5 bits of b
o  operand
i  target address in memory

Let us continue this discussion in chat.

Does this solution have unintended opcodes and if not, did you spend bytes avoiding them? See this comment for the reason I'm asking ...

@FelixPalmen Now that you mention it, yes :( Initially I observed that rule, but as I was golfing I accidentally made 4, 5, and possibly others, valid opcodes. So a decision to make their behaviour undefined would be most welcome :)

done now, I realize it wasn't the best decision in the first place and @MaxYekhlakov unfortunately didn't have to say anything about the rule change.

Do you need f←?

@EriktheOutgolfer sometimes I forget to remove it

-2 by renaming s to ⍺ so s⊢ becomes ⍺.

@Adám i like that :) thanks

JavaScript (ES6), 361 bytes
Takes input as (memory)(program_counter), where memory is an Uint8Array. Outputs by modifying this array.
M=>p=>{for(_='M[\u0011\u0011A]\u0010\u0010=\u000fc=\u000e,\u0011p]\f(n=\u000b128)\t=\u0010\b&=255\u0007,z=!(n\u0007),n&=\t;\u0006\u0006\u000b\u0005-\u0010,\u000en>=0\u0005\u0004\u0011c\b>>7,A]*2\u0005\u0003\u0011c\b&1,A]/2\u0005\u000f\u0002&&(p+=(\u0010^\t-\t;\u0001for(a=n=z=\u000ex=0;a\u0007,x\u0007,A=[i=\u0011p++],p\f\f+x][i&3],i&3&&p++,i&&A<256;)eval(`\u000ba\b\u0006\u000fa;\u000bx\b\u0006\u000fx;\u000ba&\b\u0005a|\b\u0005a^\b\u0005\u000f\u0002\u0003\u000fc*128|\u0002c|\u0003a+\b+c,\u000ea>>8\u0005++\u0010\u0005--\u0010\u0005a\u0004x\u0004++x\u0005--x\u0006\u000e1;\u000e0;1\u0001!z\u0001z\u0001!n\u0001n\u0001!c\u0001c\u0001`.split`;`[i>>2])';G=/[\u0001-\u0011]/.exec(_);)with(_.split(G))_=join(shift());eval(_)}

NB: The code is compressed with RegPack and contains a lot of unprintable characters, which are all escaped in the above representation of the source.
Try it online!
Opcode mapping and test cases
The virtual machine uses this opcode mapping.
Below are the translated test cases, along with the expected outputs.
Test case #1
00 - LDX #$10  09 10
02 - INC $01   32 01
04 - DEX       44
05 - BNE $fb   55 fb

Expected output:
$$\text{09 }\color{red}{\text{20}}\text{ 32 01 44 55 fb}$$
Test case #2
00 - (DATA)    e0 08 2a 02
04 - LDA $00   02 00
06 - ADC $02   2e 02
08 - STA $00   06 00
0a - LDA $01   02 01
0c - ADC $03   2e 03
0e - STA $01   06 01

Expected output:
$$\color{red}{\text{0a 0b}}\text{ 2a 02 02 00 2e 02 06 00 02 01 2e 03 06 01}$$
Test case #3
00 - (DATA)    5e 01 28 00
04 - LDX #$10  09 10
06 - LSR $01   1e 01
08 - ROR $00   26 00
0a - BCC $0d   65 0d
0c - LDA $02   02 02
0e - CLC       4c
0f - ADC $21   2e 21
11 - STA $21   06 21
13 - LDA $03   02 03
15 - ADC $22   2e 22
17 - STA $22   06 22
19 - ASL $02   22 02
1b - ROL $03   2a 03
1d - DEX       44
1e - BPL $e6   5d e6
20 - HLT       00
21 - (DATA)    00 00

Expected output:
$$\color{red}{\text{00 00 00 00}}\text{ 09 10 1e 01 }\dots\text{ 44 5d e6 00 }\color{red}{\text{b0 36}}$$
Unpacked and formatted
Because the code is compressed with an algorithm that replaces frequently repeated strings with a single character, it is more efficient to use the same code blocks over and over than defining and invoking helper functions, or storing intermediate results (such as M[A]) in additional variables.
M => p => {
  for(
    a = n = z = c = x = 0;
    a &= 255, x &= 255,
    A = [i = M[p++], p, M[p], M[p] + x][i & 3],
    i & 3 && p++,
    i && A < 256;
  ) eval((
    '(n = a = M[A], z = !(n &= 255), n &= 128);'                                + // LDA
    'M[A] = a;'                                                                 + // STA
    '(n = x = M[A], z = !(n &= 255), n &= 128);'                                + // LDX
    'M[A] = x;'                                                                 + // STX
    '(n = a &= M[A], z = !(n &= 255), n &= 128);'                               + // AND
    '(n = a |= M[A], z = !(n &= 255), n &= 128);'                               + // ORA
    '(n = a ^= M[A], z = !(n &= 255), n &= 128);'                               + // EOR
    '(n = M[A] = M[c = M[A] & 1, A] / 2, z = !(n &= 255), n &= 128);'           + // LSR
    '(n = M[A] = M[c = M[A] >> 7, A] * 2, z = !(n &= 255), n &= 128);'          + // ASL
    '(n = M[A] = c * 128 | M[c = M[A] & 1, A] / 2, z = !(n &= 255), n &= 128);' + // ROR
    '(n = M[A] = c | M[c = M[A] >> 7, A] * 2, z = !(n &= 255), n &= 128);'      + // ROL
    '(n = a += M[A] + c, c = a >> 8, z = !(n &= 255), n &= 128);'               + // ADC
    '(n = ++M[A], z = !(n &= 255), n &= 128);'                                  + // INC
    '(n = --M[A], z = !(n &= 255), n &= 128);'                                  + // DEC
    '(n = a - M[A], c = n >= 0, z = !(n &= 255), n &= 128);'                    + // CMP
    '(n = x - M[A], c = n >= 0, z = !(n &= 255), n &= 128);'                    + // CPX
    '(n = ++x, z = !(n &= 255), n &= 128);'                                     + // INX
    '(n = --x, z = !(n &= 255), n &= 128);'                                     + // DEX
    'c = 1;'                                                                    + // SEC
    'c = 0;'                                                                    + // CLC
    ' 1 && (p += (M[A] ^ 128) - 128);'                                          + // BRA
    '!z && (p += (M[A] ^ 128) - 128);'                                          + // BNE
    ' z && (p += (M[A] ^ 128) - 128);'                                          + // BEQ
    '!n && (p += (M[A] ^ 128) - 128);'                                          + // BPL
    ' n && (p += (M[A] ^ 128) - 128);'                                          + // BMI
    '!c && (p += (M[A] ^ 128) - 128);'                                          + // BCC
    ' c && (p += (M[A] ^ 128) - 128);')                                           // BCS
    .split`;`[i >> 2]
  )
}

Impressive :) Not a JS pro, so -- is this indexing into some "code array" by the value of the opcode? looks nice. But if this o = ... line is executed for every instruction, this might have "unintended opcodes"?

I should probably add a test case :o Now, I think it would have been better to allow unintended opcodes ... validity checks just waste bytes here, but probably too late to change the rules :(

Well, I was about to suggest exactly that, as it doesn't add much to the challenge and is now hard to check with custom mappings. But you probably should ask/warn @MaxYekhlakov first, as they may have implemented the rule correctly.

c = M[A] >> 7 & 1 <- is the &1 really needed here?

It's not. Good catch! Unfortunately, the updated source is compressed to the exact same size.

@FelixPalmen Taking directly a Uint8Array as input would save 25 bytes. Do you think that would be acceptable? I didn't find a relevant topic about that in Meta.

I'm pretty sure it would as your submission is a function anyways, my wording was "a list of bytes [...] any sensible format" and an Uint8Array indeed just encapsulates such a list of bytes. So if putting the bytes in a hex string is an acceptable way of representing the input, why should putting them in a container object be forbidden ...

How many bytes unpacked but unformatted?

@Titus 857 bytes

PHP, 581 585 555 532 bytes (not -yet- competing)
function t($v){global$f,$c;$f=8*$c|4&$v>>5|2*!$v;}$m=array_slice($argv,2);for($f=0;$p>-1&&$p<$argc-1&&$i=$m[$p=&$argv[1]];$p++)$i&3?eval(explode(_,'$a=$y_$a&=$y_$a|=$y_$a^=$y_$a+=$y+$c;$c=$a>>8_$x=$y_$c=$y&1;$y>>=1_$c=($y*=2)>>8_$y+=$y+$c;$c=$y>>8_$y+=$c<<8;$c=$y&1;$y>>=1_$y--_$y++_$z=$a-$y,$c=$a<$y_$z=$x-$y,$c=$x<$y_$y=$a_$y=$x_'.$y=&$m[[0,++$p,$g=$m[$p],$g+$x][$i&3]])[$i>>=2].'$i<14&&t(${[aaaaaxyyyyyyzz][$i]}&=255);'):($i&32?$p+=($f>>$i/8-4^$i)&1?($y=$m[++$p])-($y>>7<<8):1:($i&8?$f=$f&7|8*$c=$i/4:t($x+=$i/2-9)));print_r($m);

takes PC and and OP codes as base 10 integers from command line arguments,
prints memory as a list of [base 10 address] => base 10 value.
This is not tested thoroughly yet; but there is a breakdown.
There´s the code map
and here´s an overview for my mapping:
3-mode instructions:
00: LDA     04: AND     08: ORA     0C: EOR
10: ADC     14: LDX     18: LSR     1C: ASL
20: ROL     24: ROR     28: DEC     2C: INC
30: CMP     34: CPX     38: STA     3C: STX

+1: immediate
+2: absolute
+3: relative

implicit:
00: HLT
10: DEX 14: INX
18: CLC 1C: SEC

relative:
20: BRA         (0)
28: BNE 2C: BEQ (Z)
30: BPL 34: BMI (N)
38: BCC 3C: BCS (C)

side note:
code 24 results in a BNV (branch never = 2 byte NOP);
04, 08, 0C are aliases for INX, CLC and SEC
and anything above 3F is either a two byte NOP or an alias for the single mode instructions.


text:
Let's Play some ProSet!
ProSet is a classic card game that is played normally with 63 cards. One card has 6 colored dots on it, like below

The rest of the cards are missing some of these 6 dots, but each card has at least 1 dot. Every card in the deck is different. Below are some example valid cards.

A ProSet is a nonempty set of cards such that the total number of each color of dot is even.  For example, the above set of 4 cards are a ProSet since there are 2 reds, 4 oranges, 2 greens, 2 blues, 0 yellows, and 2 purples.
Interestingly, any set of 7 cards will contain at least 1 ProSet. Hence, in the actual card game, a set of 7 cards are presented, and the player who finds a ProSet first wins. You can try the game out for yourself here.
Challenge
Given a set of cards, each ProSet card can be assigned a value from 1 to 63 in the following manner: a red dot is worth 1 point, an orange 2 points, yellow 4, green 8, blue 16, purple 32. The sum of the values of each dot on the card is the value of the card.
Input: A list of integers from 1-63, i.e.,
[11,26,35,50]

This list represents the above 4 cards.
Output: The number of valid ProSets, which in this example is 1.
Rules

This is a code-golf challenge.
This is also a restricted-complexity challenge, as all valid solutions must be in polynomial time or less in the number of dots (in this case 6) and in the number of cards.

Test Cases
I've created an exponential algorithm to find the correct output for every input here. Again, exponential solutions are not valid submissions. But, you can use this to validate your findings.
Edit
I will address the comments in a bit.  But for now,  none of the answers have been in polynomial time. It is indeed possible,  so here's a hint: binary representation and two s complement.
Moreover, I made a mistake earlier when I said polynomial in solely dots. It needs to be polynomial in dots and cards.

Just another detail, the complexity is based in the number of dots, but what about the number of cards? can it be exponential to the number of cards?

I don't think complexity in the number of dots makes any sense since the number of dots is fixed in this problem? Wouldn't the naive solution (like Rod suggested) be exponential in the number of cards but linear in the number of dots?

Your reference implementation only checks contiguous sublists of the input.

More concrete test cases please, preferably considering any edge cases

To me, the complexity restriction spoils the challenge a little. Just code golf would have been more fun. Also, it may not be obvious if the restriction is being met by an answer or not; answer writers should explain

"A ProSet is a set of cards such that the total number of each color of dot is even" - the empty set is a set. As such the example output should be 2.

@JonathanAllen not including empty set

Out of the 6 existing answers, I don't think a single one is polynomial time. You may want to emphasize that requirement more.

Exploring the xorspace is closely related, possibly a duplicate. The number of prosets equals 2^(# elts) / (size of xorspace) - 1. I expect the polynomial-time restriction restriction to be effectively the same as finishing the xorspace test cases within a day.

@RushabhMehta No need to apologize, unexpected duplicates are common around here and I've had my share, especially with many different possibilities for terminology that can be used to phrase challenge.

@user2357112 "All current answers seem to be exponential in the number of input cards, which is worse, though" no, there is no given relationship between the number of dot-colours (the number of "dots" is said to be 6 in the example) and number of cards. All the "get the powerset of cards" solutions below, while exponential in the number of cards, are, strictly speaking, only linear in the dot-colour count (since keeping the number of cards fixed and varying the dot-colour count we can see a linear relationship).

Python 2, 60 bytes
p=[0]
for i in input():p+=[n^i for n in p]
print~-p.count(0)

Try it online!
This generate the powerset from the input (based on this answer), reducing each subset by xor.
The output will be the amount of 0s (0 = all bytes/dots appear an even number of times).
In fact the xoring is done instead of the "powerset appending", but the result is the same

This is exponential in the number of dots.

@user2357112 no, it's not, it's exponential to the numbers of cards. I've asked some clarifcation to OP when I made this answer, since I don't got an answer, I posted anyway. But it is compliant to the question as it is now.

I was about to edit (actually, delete and repost) to say "cards".

Japt, 8 bytes
à x@!Xr^

Try it here

Clojure, 182 166 149 127 bytes
(defn f[k]((frequencies(map(fn[x](reduce #(bit-xor % %2)0 x))(reduce(fn[c n](concat(map #(concat %[n])c)[(list n)]c))'()k)))0))

If I had barfed on the screen, it would've looked better than this
Try it online!

This only seems to check prefixes of the input.

Ah crap you're right. I'll update it when I have the time

Alright, that should do it.

This looks exponential time, but I don't know enough Clojure to confirm. The challenge requires a polynomial-time algorithm.

JavaScript (ES6), 53 bytes

f=
a=>a.map(i=>p.map(j=>n+=p.push(j^=i)&&!j),p=[n=0])&&n
<input oninput=o.textContent=f(this.value.split`,`)><pre id=o>

Loosely based on @Rod's Python answer.

Jelly, 8 bytes
ŒPḊ^/€¬S

A monadic Link. 9 bytes if the empty set is considered a ProSet - ŒPḊ^/€¬S‘ (since reducing an empty list errors).
Try it online!
How?
ŒPḊ^/€¬S - Link: list of integers, L
ŒP       - powerset (of cards)
  Ḋ      - dequeue (remove the empty list)
    /€   - reduce €ach with:
   ^     -   XOR
      ¬  - NOT (vectorises)
       S - sum

Python 2, 88 bytes
lambda l:~-sum(x<1for x in f(l))
f=lambda l:l and[n^l[0]for n in f(l[1:])]+f(l[1:])or[0]

Try it online!

@Downvoters could one of you explain what is wrong with this answer?

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
KoTH: Gomoku (Five in a row)
Gomoku or Five in a row is a board game played by two players on a \$15 \times 15\$ grid with black and white stones. Whoever is able to place \$5\$ stones in a row (horizontal, vertical or diagonal) wins the game.
Rules
In this KoTH we'll play the Swap2 rule, meaning that a game consists of two phases: In the initial phase the two players determine who goes first/who plays black, after that they'll place one stone each round starting with the player who picked black.
Initial phase
Let the players be A & B and A shall open the game:

A places two black and one white stone on the board
B can choose one of the following three moves:

player B decides to play black: initial phase is over
player B decides to place a white stone and plays white: initial phase is over
player B decides to play one black and one white stone: A gets to pick the color

Game phase
Each player places one stone of their colour on the board, starting with the player who plays black, this goes on until there are no more free spaces to play (in which case it's a tie) or one player manages to play \$5\$ stones in a row (in which case that player wins).
A row means either horizontal, vertical or diagonal. A win is a win - it doesn't matter whether the player managed to score more than one row.
KoTH game rules

each player plays against each other player twice:

initially it will be randomly decided who goes first
in the next game the player that got to play last goes first

a win is worth 2 points, a tie 1 and a loss 0
the goal is to score as many points as possible

Your bot
To make this challenge accessible for as many languages as possible input/output will be via stdin/stdout (line-based). The judge program will prompt your program by printing a line to your bot's stdin and your bot will print one line to stdout.
Once you receive an EXIT message you'll be given half a second to finish writing to files before the judge will kill the process.
Randomness
To make the tournaments verifiable the judge uses seeded randomization and your bot must do too, for the same reason. The bot will be given a seed via command-line argument which it should use, please refer to the next section.
Arguments
The bot receives two command-line arguments:

opponent's name
seed for randomness

User state
Because your program will always be started new for each game you'll need to use files to persist any information you want to keep. You are allowed to read/write any files or create/remove sub-folders in your current directory. You are not allowed to access any files in any parent-directory!
Input/Output format
BOARD will denote a list of the current stones, it only lists the positions where a stone is placed and each entry will be of the form ((X,Y),COLOR) where X and Y will be an integer in the range \$[0,15)\$ and COLOR will either be "B" (black) or "W" (white).
Furthermore SP denotes a single space, XY a tuple (X,Y) of two integers each in the range \$[0,15)\$ and | denotes a choice.
In the initial phase there are three different kinds of messages:
Prompt (judge) -> Answer (bot)
"A" SP "[]"  -> XY XY XY
"B" SP BOARD -> "B" | "W" SP XY | XY XY
"C" SP BOARD -> "B" | "W"

The first message asks for three tuples, the first two will be the positions of the black stones and the third one the position for the white one.
The second message asks either for:

"B" -> pick black
"W" SP XY -> pick white and place a white stone at XY
XY XY -> place two stones (first one black and second one white)

The last one just asks for which colour you want to play

After that the regular game will begin and the messages will become much simpler
N BOARD -> XY

where N is the number of the round (beginning with \$0\$) and XY will be the position where you place a stone.

There is one additional message which does not expect an answer
"EXIT" SP NAME | "EXIT TIE"

where NAME is the name of the bot that won. The second message will be sent if the game ends due to nobody winning and no more free spaces to place stones (this implies that your bot can't be named TIE).
Formatting
Since messages from the bot can be decoded without any spaces, all spaces will be ignored (eg. (0 , 0) (0,12) is treated the same as (0,0)(0,12)). Messages from the judge only contain a space to separate different sections (ie. as noted above with SP), allowing you to split the line on spaces.
Any invalid response will result in a loss of that round (you'll still receive an EXIT message), see rules.
Example
Here are some examples of actual messages:
A []
B [((0,0),"B"),((0,1),"W"),((14,14),"B")]
1 [((0,0),"B"),((0,1),"W"),((1,0),"B"),((1,1),"W"),((14,14),"B")]

Judge
You can find the judge program here: To add a bot to it simply create a new folder in the bots folder, place your files there and add a file meta containing name, command, arguments and a flag 0/1 (disable/enable stderr) each on a separate line.
To run a tournament just run ./gomoku and to debug a single bot run ./gomoku -d BOT.
Note: You can find more information on how to setup and use the judge in the Github repository. There are also three example bots (Haskell, Python and JavaScript).
Rules

on each change of a bot* the tournament will be rerun and the player with the most points wins (tie-breaker is first submission)
you may submit more than one bot as long as they don't play a common strategy
you are not allowed to touch files outside of your directory (eg. manipulating other player's files)
if your bot crashes or sends an invalid response, the current game is terminated and you lose that round
while the judge (currently) does not enforce a time-limit per round, you are advised to keep the time spent low as it could become infeasible to test all the submissions**
abusing bugs in the judge program counts as loophole

* You are encouraged to use Github to separately submit your bot directly in the bots directory (and potentially modify util.sh)!
** In case it becomes a problem you'll be notified, I'd say anything below 500ms (that's a lot!) should be fine for now.
Chat
If you have questions or want to talk about this KoTH, feel free to join the Chat!

Related

Having spaces then a meta space character in your examples is blowing my mind. Some more examples would be nice.

@Veskah: There are three example bots linked, I'll add a few examples for messages.

@Veskah: Added some examples. Btw. you can also try debugging an example bot to see what format they will be in and test what is a valid response.

You didn't give push permissions so I can't push my bot to the git

@KaitoKid: Updated.

I still don't seem to have the permission to push, or to upload files directly from the browser. I'm not familiar with Github permissions, do you need to add specific people or can you set something global?
I also tried to push to a new branch to see if the problem was with master, but the result is the same. My tortoisegit client gives me a 403.

@KaitoKid: Let us continue this discussion in chat.

KaitoBot
It uses a very crude implementation of MiniMax principles. The depth of the search is also very low, because otherwise it takes way too long.
Might edit to improve later.
It also tries to play Black if possible, because Wikipedia seems to say that Black has an advantage.
I have never played Gomoku myself, so I set up the first three stones randomly for lack of a better idea.
const readline = require('readline');
const readLine = readline.createInterface({ input: process.stdin });

var debug = true;
var myColor = '';
var opponentColor = '';
var board = [];
var seed = parseInt(process.argv[3]);

function random(min, max) {
    changeSeed();
    var x = Math.sin(seed) * 10000;
    var decimal = x - Math.floor(x);
    var chosen = Math.floor(min + (decimal * (max - min)));
    return chosen;
}

function changeSeed() {
    var x = Math.sin(seed++) * 10000;
    var decimal = x - Math.floor(x);
    seed = Math.floor(100 + (decimal * 9000000));
}

function KaitoBot(ln) {
    var ws = ln.split(' ');

    if (ws[0] === 'A') {
        // Let's play randomly, we don't care.
        var nums = [];
        nums[0] = [ random(0, 15), random(0, 15) ];
        nums[1] = [ random(0, 15), random(0, 15) ];
        nums[2] = [ random(0, 15), random(0, 15) ];
        while (nums[1][0] == nums[0][0] && nums[1][1] == nums[0][1])
        {
            nums[1] = [ random(0, 15), random(0, 15) ];
        }
        while ((nums[2][0] == nums[0][0] && nums[2][1] == nums[0][1]) || (nums[2][0] == nums[1][0] && nums[2][1] == nums[1][1]))
        {
            nums[2] = [ random(0, 15), random(0, 15) ];
        }
        console.log('(' + nums[0][0] + ',' + nums[0][1] + ') (' + nums[1][0] + ',' + nums[1][1] + ') (' + nums[2][0] + ',' + nums[2][1] + ')');
    }
    else if (ws[0] === 'B') {
        // we're second to play, let's just pick black
        myColor = 'B';
        opponentColor = 'W';
        console.log('B');
    }
    else if (ws[0] === 'C') {
        // the other player chose to play 2 stones more, we need to pick..
        // I would prefer playing Black
        myColor = 'B';
        opponentColor = 'W';
        console.log('B');
    }
    else if (ws[0] === 'EXIT') {
        process.exit();
    }
    else {
        board = [];
        var json = JSON.parse(ws[1].replace(/\(\(/g,'{"xy":[')
                .replace(/"\)/g,'"}')
                .replace(/\),/g,'],"colour":'));
        // loop over all XYs and make a board object I can use
        for (var x = 0; x < 15; x++) {
            var newRow = []
            for (var y = 0; y < 15; y++) {
                var contains = false;
                json.forEach(j => {
                    if (j.xy[0] == x && j.xy[1] == y) {
                        contains = true;
                        newRow[newRow.length] = j.colour;
                    }
                });
                if (!contains) {
                    newRow[newRow.length] = ' ';
                }
            }
            board[board.length] = newRow;
        }
        // If we never picked Black, I assume we're White
        if (myColor == '') {
            myColor = 'W';
            opponentColor = 'B';
        }
        var bestMoves = ChooseMove(board, myColor, opponentColor);
        var chosenMove = bestMoves[random(0, bestMoves.length)];
        console.log('(' + chosenMove.X + ',' + chosenMove.Y + ')');
    }
}

function IsSquareRelevant(board, x, y) {
    return (board[x][y] == ' ' &&
        ((x > 0 && board[x - 1][y] != ' ')
        || (x < 14 && board[x + 1][y] != ' ')
        || (y > 0 && board[x][y - 1] != ' ')
        || (y < 14 && board[x][y + 1] != ' ')
        || (x > 0 && y > 0 && board[x - 1][y - 1] != ' ')
        || (x < 14 && y < 14 && board[x + 1][y + 1] != ' ')
        || (y > 0 && x < 14 && board[x + 1][y - 1] != ' ')
        || (y < 14 && x > 0 && board[x - 1][y + 1] != ' ')));
}

function ChooseMove(board, colorMe, colorOpponent) {
    var possibleMoves = [];
    for (var x = 0; x < 15; x++) {
        for (var y = 0; y < 15; y++) {
            if (IsSquareRelevant(board, x, y)) {
                possibleMoves[possibleMoves.length] = {X:x, Y:y};
            }
        }
    }
    var bestValue = -9999;
    var bestMoves = [possibleMoves[0]];
    for (var k in possibleMoves) {
        var changedBoard = JSON.parse(JSON.stringify(board));
        changedBoard[possibleMoves[k].X][possibleMoves[k].Y] = colorMe;
        var value = analyseBoard(changedBoard, colorMe, colorOpponent, colorOpponent, 2);
        if (value > bestValue) {
            bestValue = value;
            bestMoves = [possibleMoves[k]];
        } else if (value == bestValue) {
            bestMoves[bestMoves.length] = possibleMoves[k];
        }
    }
    return bestMoves;
}

function analyseBoard(board, color, opponent, nextToPlay, depth) {
    var tBoard = board[0].map((x,i) => board.map(x => x[i]));
    var score = 0.0;
    for (var x = 0; x < board.length; x++) {
        var inARow = 0;
        var tInARow = 0;
        var opponentInARow = 0;
        var tOpponentInARow = 0;
        var inADiago1 = 0;
        var opponentInADiago1 = 0;
        var inADiago2 = 0;
        var opponentInADiago2 = 0;

        for (var y = 0; y < board.length; y++) {
            if (board[x][y] == color) {
                inARow++;
                score += Math.pow(2, inARow);
            } else {
                inARow = 0;
            }
            if (board[x][y] == opponent) {
                opponentInARow++;
                score -= Math.pow(2, opponentInARow);
            } else {
                opponentInARow = 0;
            }
            if (tBoard[x][y] == color) {
                tInARow++;
                score += Math.pow(2, tInARow);
            } else {
                tInARow = 0;
            }
            if (tBoard[x][y] == opponent) {
                tOpponentInARow++;
                score -= Math.pow(2, tOpponentInARow);
            } else {
                tOpponentInARow = 0;
            }

            var xy = (y + x) % 15;
            var xy2 = (x - y + 15) % 15;
            if (xy == 0) {
                inADiago1 = 0;
                opponentInADiago1 = 0;
            }
            if (xy2 == 0) {
                inADiago2 = 0;
                opponentInADiago2 = 0;
            }

            if (board[xy][y] == color) {
                inADiago1++;
                score += Math.pow(2, inADiago1);
            } else {
                inADiago1 = 0;
            }
            if (board[xy][y] == opponent) {
                opponentInADiago1++;
                score -= Math.pow(2, opponentInADiago1);
            } else {
                opponentInADiago1 = 0;
            }
            if (board[xy2][y] == color) {
                inADiago2++;
                score += Math.pow(2, inADiago2);
            } else {
                inADiago2 = 0;
            }
            if (board[xy2][y] == opponent) {
                opponentInADiago2++;
                score -= Math.pow(2, opponentInADiago2);
            } else {
                opponentInADiago2 = 0;
            }

            if (inARow == 5 || tInARow == 5) {
                return 999999999.0;
            } else if (opponentInARow == 5 || tOpponentInARow == 5) {
                return -99999999.0;
            }
            if (inADiago1 == 5 || inADiago2 == 5) {
                return 999999999.0;
            } else if (opponentInADiago1 == 5 || opponentInADiago2 == 5) {
                return -99999999.0;
            }
        }
    }

    if (depth > 0) {
        var bestMoveValue = 999999999;
        var nextNextToPlay = color;
        if (nextToPlay == color) {
            nextNextToPlay = opponent;
            bestMoveValue = -999999999;
        }
        for (var x = 0; x < board.length; x++) {
            for (var y = 0; y < board.length; y++) {
                if (IsSquareRelevant(board, x, y)) {
                    var changedBoard = JSON.parse(JSON.stringify(board));
                    changedBoard[x][y] = nextToPlay;
                    var NextMoveValue = (analyseBoard(changedBoard, color, opponent, nextNextToPlay, depth - 1) * 0.1);

                    if (nextToPlay == color) {
                        if (NextMoveValue > bestMoveValue) {
                            bestMoveValue = NextMoveValue;
                        }
                    } else {
                        if (NextMoveValue < bestMoveValue) {
                            bestMoveValue = NextMoveValue;
                        }
                    }
                }
            }
        }
        score += bestMoveValue * 0.1;
    }
    return score;
}

readLine.on('line', (ln) => {

    KaitoBot(ln);

});

EDITS: Made the seed change dynamically because otherwise when seeds exceeded 2^52 javascript couldn't handle the increment correctly

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Lucas and Fibonacci are in pair
Influenced by Non-discriminating Programming, I made up an idea of a similar challenge.
Here, we say a string is a Lucas string if the number of appearances of each character is a Lucas number (2, 1, 3, 4, 7, ...), and a string is a Fibonacci string if the number of appearances of each character is a Fibonacci number (1, 2, 3, 5, 8, ...).
Here are some concrete examples:
"Programming Puzzles"
Appearance Count:   P a e g i l m n o r s u z
                  1 2 1 1 2 1 1 2 1 1 2 1 1 2

All counts are both Lucas numbers and Fibonacci numbers, so this is both a Lucas string and a Fibonacci String
"Sandbox for Proposed Challenges"
Appearance Count:   C P S a b d e f g h l n o p r s x
                  3 1 1 1 2 1 2 3 1 1 1 2 2 4 1 2 2 1

All counts are Lucas numbers, so this is a Lucas string. However the count of o is not a Fibonacci number, so this is not a Fibonacci string.
"Here are some concrete examples: "
Appearance Count:   : H a c e l m n o p r s t x
                  5 1 1 2 2 8 1 2 1 2 1 3 2 1 1

All counts are Fibonacci, so this is a Fibonacci string. However the counts of  and e are not Lucas numbers, so this is not a Lucas string.
"Non-discriminating Programming"
Appearance Count:   - N P a c d g i m n o r s t
                  1 1 1 1 2 1 1 3 5 3 4 2 3 1 1

Since count of i is not Lucas number, and count of n is not Fibonacci number, so this is neither a Lucas string nor a Fibonacci String.
Challenge
Write 2 programs, one Lucas program and one Fibonacci program, both accepting a string as input, that:

The Lucas program checks whether the input is Fibonacci; and
The Fibonacci program checks whether the input is Lucas,

where the definitions of "Lucas" and "Fibonacci" are as above.
Rules

Your programs can choose to receive input either from STDIN or as function/program argument.
Your programs must output or return one of the 2(TWO) distinct values at your choice, one for the truthy value and one for the falsy value, and the choice must be consistent across the programs, i.e. you cannot have one program returning 0/1 while the other one returning true/false.
Your programs must output or return a truthy value if the source of each other is inputted, i.e. your Lucas program must return a truthy value if the source of your Fibonacci program is inputted, and vice versa.
It is allowed to have program being both Lucas and Fibonacci.
Characters not used are apparently not counted, in case you doubt because 0 is not in the Lucas sequence.
Number of distinct characters in each program are not restricted to either Lucas or Fibonacci numbers.
Only full programs or functions allowed. Snippets are not accepted.
Standard loopholes are apparently forbidden.

Scoring
The score will be calculated as follows:

For each program, multiply the number of distinct characters used by the maximum number of appearances of the characters in the source.
Add the two values calculated in the previous step up. This is your score.

Example:
Lucas code :    20 distinct characters, MAX(appearance of each character)=7
Fibonacci code: 30 distinct characters, MAX(appearance of each character)=5
Score: 20*7 + 30*5 = 140 + 150 = 290

Test cases
Input                                   | Output of ...
                                        | Lucas Program      | Fibonacci Program
----------------------------------------+---------------------------------------
<Your Lucas program>                    | True if all appe-  | True
(Lucas string by rules)                 | arance counts are  |
                                        | exactly 1, 2 or 3; |
                                        | False otherwise    |
----------------------------------------+--------------------+------------------
<Your Fibonacci program>                | True               | True if all appe-
(Fibonacci string by rules)             |                    | arance counts are
                                        |                    | exactly 1, 2 or 3;
                                        |                    | False otherwise
----------------------------------------+--------------------+------------------
"Programming Puzzles"                   | True               | True
(Both Lucas and Fibonacci)              |                    |
----------------------------------------+--------------------+------------------
"Sandbox for Proposed Challenges"       | False              | True
(Lucas but not Fibonacci)               |                    |
----------------------------------------+--------------------+------------------
"Here are some concrete examples: "     | True               | False
(Fibonacci but not Lucas)               |                    |
----------------------------------------+--------------------+------------------
"Non-discriminating Programming"        | False              | False
(Neither Lucas nor Fibonacci)           |                    |
----------------------------------------+--------------------+------------------
"Hello world!"                          | True               | True
(Both Lucas and Fibonacci)              |                    |
----------------------------------------+--------------------+------------------
"18446744073709551616"                  | False              | True
(Lucas but not Fibonacci)               |                    |
----------------------------------------+--------------------+------------------
"Lucas and Fibonacci are IN pair"       | True               | False
(Fibonacci but not Lucas)               |                    |
----------------------------------------+--------------------+------------------
"Lucas and Fibonacci are in pair"       | False              | False
(Neither Lucas nor Fibonacci)           |                    |

Winning Criteria
The submission with the lowest score in each language wins.

"Lucas and Fibonacci are IN pair (Fibonacci but not Lucas)" You've swapped the True and False in your table.

@Mr.Xcoder I don't see anything stating that. Two programs where each characters is used once should be fine I think. But I'll let OP verify/deny that.

@Mr.Xcoder Besides, in the Truthy/Falsey table the Lucas program as input in the Lucas program states: "True if all appearance counts are exactly 1, 2 or 3; False otherwise", and similar in the Fibonacci program and input columns.

I see, but I think this should be clarified in the Rules section. I thought they ought to be mutually exclusively either Fib or Lucas.

@Mr.Xcoder I can definitely understand your confusion. I've re-read the challenge a few times myself to make sure. Still waiting for OP to verify and edit however..

@KevinCruijssen Since the Lucas program checks whether the input is Fibonacci, so there is no problem in that row I think.

@Mr.Xcoder I have edited to clarify that it is allowed to have program being both Lucas and Fibonacci. As long as the two programs do different jobs accordingly.

05AB1E, score: 10 + 8 = 18
This could be a comment on Kevin's post, but I've developed it independently and the technique is slightly different. Therefore I am posting it myself.
Fibonacci program that checks Lucas (10 bytes)
€¢Dā0šÅgÃQ

Try it online!
€¢Dā0šÅgÃQ -> Full program
€¢         -> Count the occurrences of each character in the string. Call this list C.
  Dā       -> Duplicate and yield the range [1 ... len string].
    0š     -> Prepend 0. [0 ... len string].
      Åg   -> Nth Lucas number (for each).
        Ã  -> Intersection with C.
         Q -> Check equality with C.

Lucas program that checks Fibonacci (8 bytes)
€¢DāÅfÃQ

Try it online!
€¢DāÅfÃQ -> Full program
€¢       -> Count the occurrences of each character in the string. Call this list C.
  Dā     -> Duplicate and yield the range [1 ... len string].
    Åf   -> Nth Fibonacci number (for each). We don't need the 0th this time!
      Ã  -> Intersection with C.
       Q -> Check equality with C.

Nice approach, but I'm afraid the Lucas program fail for single-char inputs because the list starts with [2,1,...]. So the Dā<Åg would be [2] with the count [1], returning in a falsey result. The Fibonacci program is perfect, though. :)

@KevinCruijssen Fixed. AHHH, Lucas sequence, why do you have to be non-increasing?!

I know the feeling.. Screwed up my initial program as well. Too bad the ∞ is [1,INF] instead of [0,INF], otherwise I would have used that instead of Z>.

05AB1E, score: 19 17 (9x1 + 8x1)
-2 score thanks to @Emigna.
Lucas (10 9 bytes):
€¢Z>ÅGKg_

Try it online (with the Fibonacci program as input).
Verify all test cases.
Fibonacci (9 8 bytes):
€¢ZÅFKg_

Try it online (with the Lucas program as input).
Verify all test cases.
Outputs 1 for truthy and 0 for falsey results.
Explanation:
€¢          # Count each of the characters in the input
            #  i.e. "Programming Puzzles" → [2,2,1,2,2,1,2,2,1,1,2,1,2,1,2,2,1,1,1]
  Z         # Get the max, without popping the list
            #  i.e. [2,2,1,2,2,1,2,2,1,1,2,1,2,1,2,2,1,1,1] → 2
   >ÅG      # Calculate the Lucas numbers up to and including this max+1
            # (Note: the +1 is because `1ÅG` returns `[]` instead of `[1]`)
            #  i.e. 2 → [2,1]
   ÅF       # Calculate the Fibonacci numbers up to and including this max
            #  i.e. 2 → [0,1,1,2]
     K      # Remove all these Fibonacci numbers from the count list
            #  i.e. [2,2,1,2,2,1,2,2,1,1,2,1,2,1,2,2,1,1,1] and [2,1] → []
            #  i.e. [2,2,1,2,2,1,2,2,1,1,2,1,2,1,2,2,1,1,1] and [0,1,1,2] → []
      g_    # Check if the list is not empty
            #  i.e. [] → 0

The test cases in TIO should be swapped, aren't they? Both programs are both Lucas and Fibonacci tho ;)

@user71546 Should be fixed now. Also added an explanation and test suite.

@KevinCruijssen How about the Both programs are both Lucas and Fibonacci tho point?

@Mr.Xcoder I had the Fibonacci program as input in the Fibonacci TIO, and Lucas program in the Lucas TIO. Hence user71546 stated the test cases should be swapped. The "Both programs are both Lucas and Fibonacci tho ;)" part I read as: "Not that it matters that they are swapped, since both programs are both a Lucas and Fibonacci program anyway. ;)" As mentioned in my other comment, I don't see anything indicating the programs can't be both a Lucas AND Fibonacci program, similar as the test case "Programming Puzzles".. Will delete and/or fix if this is not allowed.

Do you really need the ês?

@Emigna Thanks for -2 score! Not sure why I had that now that I think about it. Hmm.. time to update my Java answer as well it seems. ;)

Perl 6, 32*2 + 33*2 = 171 130
-41 points thanks to nwellnhof!

Lucas Program:
{min([values .ords⊎e]».&{$_∈(1,1,*+*…0)[0…$_]})}

Fibonacci Program:
{min([values .ords⊎e]».&{$_∈(2,1,*+*…0)[0…$_]})}

Try it online!
Anonymous code blocks that take a string and return a Junction (which can be coerced to truthy/falsey values). Both use the same structure rearranged to get the correct amount of characters.
Explanation:
{min([values .ords⊎e]».&{$_∈(1,1,*+*…0)[0…$_]})}

{  # Anonymous code block
  min(  # Find the minimum of:
      [values .ords⊎e]  # Coerces the string to a list of the number of occurrences
                      ».&{ # Map each value to:
                          $_∈  # Whether the value is an element of:
                             (1,1,*+*…0)   # The sequence
                                        [0…$_]  # Truncated to prevent it evaluating infinitely
                         }
     )
}

Jelly,  19  8×1+9×1=17
code-page
Lucas Program:
ĠẈfƑJÆḞ$

Try it online! Or see all-tests.
Fibonacci Program:
ĠẈfƑJŻÆĿƊ

Try it online! Or see all-tests.
How?
Both work in very similar fashions -- ÆḞ gets the nth Fibonacci number while ÆĿ gets the nth lucas number. Ż adds a zero to the front of the list of n's to use with ÆĿ to cater for the fact that the 0th Lucas number is 2, which  we need to test for while 0 is the 0th Fibonacci number, which we do not need to test for. Ɗ is a quick to chain the last three links together as a monad, while $ chains the last two links together as a monad...
Lucas Program:
ĠẈfƑJÆḞ$ - Link: list of characters, s
Ġ        - group indices by value
 Ẉ       - length of each
       $ - last two links as a monad (f(s))
    J    -   range of length of s
     ÆḞ  -   nth Fibonacci number (vectorises)
   Ƒ     - is left argument is equal to the result of?:
  f      -   filter - remove items from left that are not in right
         -            i.e. groupLengths without those Fibonacci numbers

Fibonacci Program:
ĠẈfƑJŻÆĿƊ - Link: list of characters, s
Ġ         - group indices by value
 Ẉ        - length of each
        Ɗ - last three links as a monad (f(s))
    J     -   range of length of s
     Ż    -   prepend a zero
      ÆĿ  -   nth Lucas number (vectorises)
   Ƒ      - is left argument is equal to the result of?:
  f       -   filter - remove items from left that are not in right
         -            i.e. groupLengths without those Lucas numbers

Java 8, score 1238 1137 (35x18 + 39x13)
Lucas:
c->c.chars().map(a->c.length()-c.replace(""+(char)a,"").length()).allMatch(a->{int n=2,s=1,m=3;for(;a>m;n=s,s=m)m=n+s;return a>0&a<4|a==m;})//",-..mmnrr

Try it online.
Fibonacci:
s->s.chars().map(e->s.length()-s.replace(""+(char)e,"").length()).allMatch(a->{int l=(int)Math.sqrt(a=5*a*a+4);return(l*l==a|(l=(int)Math.sqrt(a-=8))*l==a);})//--...===aaanl((((()))))

Try it online.
Explanation (base) Lucas:
s->                     // Method with String parameter and boolean return-type
  s.chars()             //  Loop over the characters as integer-stream
   .map(c->             //  Map each of them to:
     s.length()-s.replace(""+(char)c,"").length())
                        //   The occurrence-count of this character in the input
   .allMatch(n->{       //  Check if all these occurrence-counters are true for:
      int a=2,b=1,c=3;  //    Integer `a`,`b`,`c` starting at 2,1,3 (start of Lucas sequence)
      for(;n>c;         //    Loop as long as the current occurrence-counter is larger than `c`
          ;             //      After every iteration:
           a=b,         //       Replace `a` with `b`
           b=c)         //       Replace `b` with `c`
        c=a+b;          //     Replace `c` with `a` + `b`
      return            //    Return whether the occurrence-counter is one of:
             n>0&n<4    //     1,2,3,
             |n==c;})   //     or `c`

Explanation (base) Fibonacci:
s->                     // Method with String parameter and boolean return-type
  s.chars()             //  Loop over the characters as integer-stream
   .map(c->             //  Map each of them to:
      s.length()-s.replace(""+(char)c,"").length())
                        //   The occurrence-count of this character in the input
   .allMatch(n->{       //  Check if all these occurrence-counters are true for:
      int r=(int)Math.sqrt(n=5*n*n+4);
                        //   Integer `r`, the square of `5*n*n+4` floored
      return r*r==k     //  Return whether `5*n*n+4` is a perfect square,
             |(r=(int)Math.sqrt(n-=8))*r==n;})
                        //  and/or if `5*n*n-4` is a perfect square

A number \$n\$ is a Fibonacci number, if either or both of \$5n^2+4\$ or \$5n^2-4\$ is a perfect square (source)
Explanation modifications:
After these base programs explained above, I've made the following changes:

Changed the names of variables to only use letters we've already used to reduce amount of distinct characters; and also so the least amount of characters have to be added at the comment to make the occurrence-counts Lucas/Fibonacci numbers;
Added parenthesis around the return-statement (to get rid of the space as well);
Put any remaining character we need to increase for it to become a Lucas/Fibonacci number after the trailing comment //.

Pyt, 11*1+12*1=23 bytes
Both return 0 as truthy, 1 as falsy
Fibonacci test:
ĐỤ⇹ɔ2ᴇřḞ\Ł±

Try it online!
Lucas test:
ĐỤ⇹ɔ02ᴇŘĿ\Ł±

Try it online!
Explanation:
                    Implicit input
Đ                   Duplicate the input
 Ụ                  Get list of unique characters
  ⇹                 Swap the top two elements on the stack
   ɔ                Count the number of occurrences of each character in the input
    2ᴇř             Push [1,...,100] (should be more than enough)
       Ḟ            Get the first 100 Fibonacci numbers
        \           Get all character counts that aren't Fibonacci numbers
         Ł          Get the number of such counts
          ±         Output the sign of the number of such counts
                    Implicit output

                    Implicit input
ĐỤ⇹ɔ                get count of occurrences of each character
    02ᴇŘ            Push [0,1,...,100] (should be more than enough)
        Ŀ           Get the first 101 Lucas numbers
         \          Get all character counts that aren't Lucas numbers
          Ł         Get the number of such counts
           ±        Output the sign of the number of such counts
                    Implicit output


text:
Missing numbers in arithmetic sum
Challenge
Giving a valid arithmetic sum with some missing numbers, output the full expression.
Example:
    1#3                 123
+   45#     =>     +    456
--------            --------
    579                 579

Input

Expression format can be an array ["1#3", "45#", "579"], a string "1#3+45#=579", or 3 inputs f("1#3","45#","579")

Output

Same as input
You don't need to output the result

Notes

The missing numbers are going to be represented using # or any other constant non-numeric character you want
Assume result wont have a missing number
Assume Input/Output consist in 2 terms and a final result
Assume both term > 0 and result >= 2
There might be multiple solutions. You can output anyone as long as the sum result match

Test Cases with possibly outputs (pretty format)
    #79                     879
+   44#         =>      +   444
--------                --------
    1323                   1323

    5#5                     555
+   3#3         =>      +   343
--------                --------
    898                     898

      #                       1
+     #         =>      +     1
--------                --------
      2                       2

    ###                     998
+   ###         =>      +     1     PD: there are a lot of possible outputs for this one
--------                --------
    999                     999

    123                     123
+     #         =>      +     1
--------                --------
    124                     124

      9                       9
+    #6         =>      +    46
--------                --------
     55                      55

    #123651                     1123651
+      #98#         =>      +      7981
------------                -----------
    1131632                     1131632

Standard code-golf rules apply

Do we need to strip leading zeros?

@Mnemonic not necessarily

can I take the input with the sides around = swapped? e.g. 579=1#3+45#

@dzaima yes , no problem

test-case request: ###+###=2

"Assume both term > 0" does "assume" mean that I have to output both terms > 0 or that I can assume that there's always a solution with both > 0 but output whatever?

also your added test-case avoids exactly what I was asking for - the leading zeroes

Distantly related (as in: both require fixing arithmetic equations).

Can I take input with == instead of =?

Brachylog, 22 16 bytes
{Ṣ∧Ị∋|}ᵐ²ịᵐ.k+~t

Try it online!
-6 bytes thanks to @Fatelize
Explanation
{Ṣ∧Ị∋|}ᵐ²ịᵐ.k+~t
{     }ᵐ²                   #   for each letter in each string
 Ṣ∧Ị∋                       #       if " " return a digit; else input
     |                      #
         ịᵐ                 #   cast each string to number
            k+              #   the sum of all but the last one
              ~t            #       is equal to the last one
           .                #   output that list

{"#"∧Ị∋|}ᵐ²ịᵐ.k+~t is 4 bytes shorter. I'm not sure why you did something this convoluted in your map.

Since we can use any non-numeric character, you should use e.g. space with Ṣ instead of "#" which will save two more bytes.

JavaScript (ES6), 74 57 bytes
Takes input as (a)(b)(result), where a and b are strings with . for unknown digits and result is an integer. Returns an array of 2 integers.
a=>b=>F=(c,n)=>`${r=[c,n]}`.match(`^`+[a,b])?r:F(c-1,-~n)

Try it online!
Commented
a => b =>                // a, b = term patterns (e.g. a = ".79", b = "44.")
  F = (c,                // c = expected result (e.g. 1323)
          n) =>          // n = guessed value of b, initially undefined
    `${r = [c, n]}`      // we coerce r = [c, n] to a string (e.g. "879,444")
                         // if n is still undefined, this gives just c followed by a comma
    .match(`^` + [a, b]) // we coerce [a, b] to a string, prefixed with "^" (e.g. "^.79,44.")
    ?                    // this is implicitly turned into a regular expression; if matching:
      r                  //   return r
    :                    // else:
      F(c - 1, -~n)      //   decrement c, increment n and do a recursive call

Ah, so that's what's happening. I tried to understand your code without explanation yesterday (and I'm bad at JS), but didn't understand why -~n couldn't be just n+1 and how F=(c,n)=> was used. Now that you added an explanation it all makes sense. c is the third input, n is undefined (and ~undefined becomes -1 unlike undefined+1). All clear now (and not something I can port to Java unfortunately, which was mainly why I tried to understand it xD). PS: Already upvoted yesterday, so I just upvoted one of your other answers (which I didn't upvote already, not a lot available..) ;p

@KevinCruijssen FWIW, I wrote a tip about this some times ago. But yeah ... that's a JS thing and is probably not portable to many other languages.

Well, I might be able to semi-port it but just creating a recursive second method, and using a ternary-if to check for null, manually converting it to -1. However, Java has a (very) limited recursive StackOverflow limit, so using a recursive method with randomness hoping it would end up correct within about 1024 recursive calls isn't going to work anyway in Java. Ah well. I've upvoted your tip. Have a nice weekend! :)

@KevinCruijssen My first JS attempt was doing exactly that: trying random values with a recursive function. And it was usually doing significantly less iterations than the one using a counter. Fun fact: even for ###+###=999, your odds are 1 in 1000. So with 1024 iterations, you should succeed slightly more often than you fail. :)

Matlab, 143 134 132 119 115 bytes
function[m]=f(x,y,r),p=@(v)str2num(strrep(v,'#',char(randi([48,57]))));m=[1,1];while sum(m)-r,m=[p(x),p(y)];end;end

-4 bytes thanks to @Luismendo
Try it Online

Pretty big and pretty stupid. It simply replaces all # with random digits until it finds the correct ones.

R, 67 51 bytes
Rock simple and scales horribly, just grep all the sum combinations. Use "." for unknown digits. It won't find the same answer as test case number 4, but it will give a possible answer, which follows the letter of the rules as given.
-16 bytes by grepping after forming the output and replacing paste with the ? operator.
function(x,y,z,`?`=paste)grep(x?y,1:z?z:1-1,v=T)[1]

Try it online!

Awesome idea, I would never have thought of that. You can save a few bytes by using * in place of grepl : https://tio.run/##PYzLCoMwEEX3/YqSRUlkDExiUiP6JSIIUh9QbJGUqj@fxkS6uZc5c2YW15ep6z9zZ6fXTFfYYAdb7QWmCG3SVsPyeD9ZR4cy/Y5TN9I1wWK/bYllNTZg66FhrqeE3w0BkmXcJ0ohCbt4qrgicCWSy6Nyk0fMjymEOAGPKJQxJkAU8u@hyKJpAtJHKnUee1ErDAuTRx0laumfux8

I was looking for various operators and you come up with ?... I think this is a first.  by the way, I forgot if I already told you but we're trying to get R nominated for september language of the month - you can upvote if not done already.

I could've chosen anything with low precedence. Feels like there should be a better way to get the match...

Charcoal, 32 bytes
Ｆ²⊞υ0Ｗ⁻ζΣＩυ≔Ｅ⟦θη⟧⭆κ⎇⁼μ#‽χμυ←Ｅυ⮌ι

Try it online! Link is to verbose version of code. Explanation:
Ｆ²⊞υ0

Push two string 0s to the predefined empty list u to get the while loop going.
Ｗ⁻ζΣＩυ

Repeat while the sum of casting the values in u to integer is not equal to the desired result.
≔Ｅ⟦θη⟧

Create an array of the two inputs and map over it.
⭆κ⎇⁼μ#‽χμυ

Replace each # with a random digit and assign the result back to u.
←Ｅυ⮌ι

Print the result right justified. (Left justified would be just υ for a 4-byte saving.)

Jelly, 20 bytes
ØDṛċ¡V€)ŒpḌð€ŒpS⁼¥ƇḢ

Try it online!

05AB1E (legacy), 23 20 bytes
[²³«εð9ÝΩ:}²gôJDO¹Q#

-3 bytes thanks to @Emigna.
Unknown digits are spaces ( ). Input order should be: expected result; longest string; shortest string.
Try it online.
Explanation:
[                 # Start an infinite loop
 ²³«              #  Take the second and third inputs, and merge them together
               #   i.e. " 79" and " 4 " → " 79 4 "
    ε     }    #  Map each character to:
     ð   :     #   Replace a space with:
      9ÝΩ      #   A random digit in the range [0,9]
               #    i.e. " 79 4 " → ['3','7','9','2','4','3']
               #    i.e. " 79 4 " → ['5','7','9','7','4','4']
²g             #  Get the length of the second input
               #   i.e. " 79" → 3
  ô            #  And split it into two numbers again
               #   i.e. ['3','7','9','2','4','3'] and 3 → [['3','7','9'],['2','4','3']]
               #   i.e. ['5','7','9','7','4','4'] and 3 → [['5','7','9'],['7','4','4']]
   J           #  Join each list together to a single number
               #   i.e. [['3','7','9'],['2','4','3']] → [379,243]
               #   i.e. [['5','7','9'],['7','4','4']] → [579,744]
    D          #  Duplicate this list
     O         #  Sum the list
               #   i.e. [379,243] → 622
               #   i.e. [579,744] → 1323
      ¹Q#      #  If it's equal to the first input: stop the infinite loop
               #  (and output the duplicate list implicitly)
               #   i.e. 1323 and 622 → 0 (falsey) → continue the loop
               #   i.e. 1323 and 1323 → 1 (truthy) → stop the loop and output [579,744]

Replace saves 3 over the if.

@Emigna Ah, of course. Thanks!

Perl 6, 81 74 bytes
-7 bytes thanks to nwellnhof!
{first {try S/\=/==/.EVAL},map {$^a;S:g[\#]=$a[$++]},[X] ^10 xx.comb('#')}

Try it online!
Anonymous code block that takes input as a string containing an arithmetical expression e.g. "12#+45#=579". Substitutes each # with possible permutations of digits, substitutes the= with == and finds the first valid result.
Explanation:
{  # Anonymous code block                                                      }
 first   # Find the first of:
                                                               ^10  # The range of 0 to 9
                                                                   xx.comb('#') # Multiplied by the number #s in the code
                                                          ,[X]  # The cross-product of these lists
                          map   # Map each crossproduct to:
                              {$^a;.trans: "#"=>{$a[$++]}}  # The given string with each # translated to each element in the list
      {try S/\=/==/.EVAL}, # Find which of these is true when = are changed to == and it is eval'd

You can use S:g[\#]=$a[$++] instead of trans for 74 bytes.

@nwellnhof I didn't realise you could use S/// in that sort of syntax! Thanks!

APL (Dyalog Unicode), 22 bytes
{'#'⎕R{⍕?10}t}⍣{⍎⍺}t∘←

Try it online!

Java 10, 203 198 193 bytes
(a,b,c)->{int A=0,B=0,l=a.length();for(a+=b,b="";A+B!=c;A=c.valueOf(b.substring(0,l)),B=c.valueOf(b.substring(l)),b="")for(var t:a.getBytes())b+=t<36?(t*=Math.random())%10:t-48;return A+"+"+B;}

Try it online.
Explanation:
(a,b,c)->{           // Method with 2 Strings & integer parameters and String return-type
  int A=0,B=0,       //  Result-integers, starting both at 0
      l=a.length();  //  Length of the first String-input
  for(a+=b,          //  Concat the second String-input to the first
      b="";          //  Reuse `b`, and start it as an empty String
      A+B!=c         //  Loop as long as `A+B` isn't equal to the integer-input
      ;              //    After every iteration:
       A=c.valueOf(b.substring(0,l)),
                     //     Set `A` to the first String-part as integer
       B=c.valueOf(n.substring(l)),
                     //     Set `B` to the second String-part as integer
       b="")         //     Reset `b` to an empty String
    for(var t:a.getBytes())
                     //   Inner loop over the characters of the concatted String inputs
      b+=t<36?       //    If the current character is a '#':
          (t*=Math.random())%10
                     //     Append a random digit to `b`
         :           //    Else (it already is a digit):
          t-48;      //     Append this digit to `b`
  return A+"+"+B;}   //  After the loop, return `A` and `B` as result

Python 3, 121 155  152  149 bytes
import re
def f(i,k=0,S=re.sub):s=S('#','%s',i)%(*list('%0*d'%(i.count('#'),k)),);print(s)if eval(S('=','==',S('\\b0*([1-9])','\\1',s)))else f(i,k+1)

Try it online!
+34 New solution with regex to circumvent the fact that python doesn't support numbers with leading zeroes.
-3 thanks to @Jonathan Frech

The old solution doesn't work if # is the first character in any number (because eval doesn't accept leading zeroes) and is therefore invalid :(
def f(i,k=0):
 s=i.replace('#','%s')%(*list('%0*d'%(i.count('#'),k)),)
 print(s)if eval(s.replace('=','=='))else f(i,k+1)

Try it online!

I'm afraid this submission is invalid for the reason stated in the post.

Since your function does not contain any compound statements you can condense it to only one line.

C# .NET, 225 220 196 bytes
(a,b,c)=>{int A=0,B=0,l=a.Length;for(a+=b,b="";A+B!=c;A=int.Parse(b.Substring(0,l)),B=int.Parse(b.Substring(l)),b="")foreach(var t in a)b+=(t<36?new System.Random().Next(10):t-48)+"";return(A,B);}

Port of my Java 10 answer.
(I'm very rusty in C# .NET golfing, so can defintely be golfed..)
-3 bytes implicitly thanks to @user82593 and this new C# tip he added.
-29 bytes thanks to @hvd.
Try it online.
Explanation:
(a,b,c)=>{        // Method with 2 string & int parameters and int-tuple return-type
  int A=0,B=0,    //  Result-integers, starting both at 0
      l=a.Length; //  Length of the first string-input
  for(a+=b,       //  Concat the second string-input to the first
      b="";       //  Reuse `b`, and start it as an empty string
      A+B!=c      //  Loop as long as `A+B` isn't equal to the integer-input
      ;           //    After every iteration:
       A=int.Parse(b.Substring(0,l)),
                  //     Set `A` to the first string-part as integer
       B=int.Parse(b.Substring(l)),
                  //     Set `B` to the second string-part as integer
       b="")      //     Reset `b` to an empty string
    foreach(var t in a)
                  //   Inner loop over the characters of the concatted string inputs
      b+=(t<36?   //    If the current character is a '#':
           new System.Random().Next(10)
                  //     Use a random digit
          :       //    Else (it already is a digit):
           t-48)  //     Use this digit as is
         +"";     //    And convert it to a string so it can be appended to the string
  return(A,B);}   //  After the loop, return `A` and `B` in a tuple as result

You can use the regular using System; instead, it is shorter than namespace System{}.

@hvd That was it!.. I haven't done C# in years, lol.. I tried using System.*; similar as imports in Java, but that didn't work. Forgot I had to remove the .* part.. Thanks for the -5 bytes.

Re-reading it now, that was actually a sub-optimal suggestion. You can write int.Parse (-4), use new System.Random() (+7) and drop using System; (-13) to save another 10 bytes. :) Also, you do not need .ToCharArray(), that takes off 14 more bytes.

@hvd Thanks! Not sure how I forgot about int.Parse vs System.Int32.Parse... It's basically the same as System.String and string.. And didn't knew it was possible to loop over the characters without the .ToCharArray(). Thanks for another -24 bytes. :D

C (gcc), 228 213 203 172 170 bytes
-15 Bytes thanks to @ceilingcat. I've never used index before.
-10 Bytes thanks to @Logem. Preprocessor magic
refactored call to exit(0) with puts as parameter.
char*c,*p[9],k;main(i,v)int**v;{for(i=X[1],35))||X[2],35))?p[k++]=c,main(*c=57,v):k;!c*i--;)47==--*p[i]?*p[i]=57:Y[1])+Y[2])^Y[3])?main(i,v):exit(puts(v[2],puts(v[1])));}

Try it online!

194 bytes - Try it online!

You can save two bytes replacing the macro -DX=c=index(v, with -DX=(c=index(v, TIO link in my last comment.

Thanks guys.  Doesn't look like I even tried to golf this before...

Powershell, 91 byte
The script finds all solutions. The total number of iterations is 10 power the number of characters #. The recursion depth is equal to the number of characters #.
filter f{$h,$t=$_-split'#',2
if($t){0..9|%{"$h$_$t"}|f}elseif($h-replace'=','-eq'|iex){$h}}

Test script:
filter f{$h,$t=$_-split'#',2
if($t){0..9|%{"$h$_$t"}|f}elseif($h-replace'=','-eq'|iex){$h}}

@(
    ,('1#3+45#=579','123+456=579')
    ,('#79+44#=1323','879+444=1323')
    ,('5#5+3#3=898','505+393=898 515+383=898 525+373=898 535+363=898 545+353=898 555+343=898 565+333=898 575+323=898 585+313=898 595+303=898')
    ,('#+#=2','0+2=2 1+1=2 2+0=2')
    ,('9+#6=55','9+46=55')
    ,('123+##=124','123+01=124')
    ,('#123651+#98#=1131632','1123651+7981=1131632')
    ,('##+##=2','00+02=2 01+01=2 02+00=2')
    ,('##+##=99','00+99=99 01+98=99 02+97=99 03+96=99 04+95=99 05+94=99 06+93=99 07+92=99 08+91=99 09+90=99 10+89=99 11+88=99 12+87=99 13+86=99 14+85=99 15+84=99 16+83=99 17+82=99 18+81=99 19+80=99 20+79=99 21+78=99 22+77=99 23+76=99 24+75=99 25+74=99 26+73=99 27+72=99 28+71=99 29+70=99 30+69=99 31+68=99 32+67=99 33+66=99 34+65=99 35+64=99 36+63=99 37+62=99 38+61=99 39+60=99 40+59=99 41+58=99 42+57=99 43+56=99 44+55=99 45+54=99 46+53=99 47+52=99 48+51=99 49+50=99 50+49=99 51+48=99 52+47=99 53+46=99 54+45=99 55+44=99 56+43=99 57+42=99 58+41=99 59+40=99 60+39=99 61+38=99 62+37=99 63+36=99 64+35=99 65+34=99 66+33=99 67+32=99 68+31=99 69+30=99 70+29=99 71+28=99 72+27=99 73+26=99 74+25=99 75+24=99 76+23=99 77+22=99 78+21=99 79+20=99 80+19=99 81+18=99 82+17=99 83+16=99 84+15=99 85+14=99 86+13=99 87+12=99 88+11=99 89+10=99 90+09=99 91+08=99 92+07=99 93+06=99 94+05=99 95+04=99 96+03=99 97+02=99 98+01=99 99+00=99')
) | % {
    $s,$e = $_
    $r = $s|f
    "$($e-eq$r): $r"
}

Powershell, 'Assume both term > 0' is mandatory, 110 bytes
filter f{$h,$t=$_-split'#',2
if($t){0..9|%{"$h$_$t"}|f}else{$a,$b,$c=$_-split'\D'
$_|?{+$a*+$b*!(+$a+$b-$c)}}}

PHP, 112 bytes
lame brute force solution
for(;$s=$argn;eval(strtr($s,['='=>'==','#'=>0]).'&&die($s);'))for($k=$n++;$k;$k=$k/10|0)$s[strpos($s,35)]=$k%10;

takes string as input, stops at first solution. Run as pipe with -nR or try it online.


text:
Sorting out redundant text from screen scraper application
You are writing a screen scraper application monitoring a text-only chat window. Text is added at the bottom of the window.
The application takes screenshot of the chat window. If a change has occurred since last screenshot (new_screenshot != old_screenshot), the screenshot is saved.
After X time, all images are merged to one image, where the oldest image is on the top. This large image is send to a server for OCR, and a string of text is returned.
Challenge: Sort out redundant text.
Example: Chat window is 5 lines high and is initially empty. The solution must work with empty and not-empty initial chat window. More than one line can be added at each screenshot.
Input to algorithm:
1 Lorem ipsum dolor sit amet,
1 Lorem ipsum dolor sit amet,
2 consectetur adipiscing elit
1 Lorem ipsum dolor sit amet,
2 consectetur adipiscing elit
3 Mauris porttitor enim sed tincidunt interdum.
1 Lorem ipsum dolor sit amet,
2 consectetur adipiscing elit
3 Mauris porttitor enim sed tincidunt interdum.
4 Morbi elementum erat nec nulla auctor, eget porta odio aliquet.
1 Lorem ipsum dolor sit amet,
2 consectetur adipiscing elit
3 Mauris porttitor enim sed tincidunt interdum.
4 Morbi elementum erat nec nulla auctor, eget porta odio aliquet.
5 Nam aliquet velit vel elementum tristique.
2 consectetur adipiscing elit
3 Mauris porttitor enim sed tincidunt interdum.
4 Morbi elementum erat nec nulla auctor, eget porta odio aliquet.
5 Nam aliquet velit vel elementum tristique.
6 Donec ac tincidunt urna.
3 Mauris porttitor enim sed tincidunt interdum.
4 Morbi elementum erat nec nulla auctor, eget porta odio aliquet.
5 Nam aliquet velit vel elementum tristique.
6 Donec ac tincidunt urna.
7 Proin pretium, metus non porttitor lobortis, tortor sem rhoncus urna
4 Morbi elementum erat nec nulla auctor, eget porta odio aliquet.
5 Nam aliquet velit vel elementum tristique.
6 Donec ac tincidunt urna.
7 Proin pretium, metus non porttitor lobortis, tortor sem rhoncus urna
8 quis finibus leo lorem sed lacus.
5 Nam aliquet velit vel elementum tristique.
6 Donec ac tincidunt urna.
7 Proin pretium, metus non porttitor lobortis, tortor sem rhoncus urna
8 quis finibus leo lorem sed lacus.
1 Lorem ipsum dolor sit amet,
Expected result:
1 Lorem ipsum dolor sit amet,
2 consectetur adipiscing elit
3 Mauris porttitor enim sed tincidunt interdum.
4 Morbi elementum erat nec nulla auctor, eget porta odio aliquet.
5 Nam aliquet velit vel elementum tristique.
6 Donec ac tincidunt urna.
7 Proin pretium, metus non porttitor lobortis, tortor sem rhoncus urna
8 quis finibus leo lorem sed lacus.
1 Lorem ipsum dolor sit amet,
UPDATE: I forgot an important detail in the original challenge: The same line can come multiple times, but never two times in a row so just deduplicating is not enough.

Welcome to PPCG! This site is a language-agnostic challenge site, it's not like StackOverflow. I've tried to edit your question to stay on topic. If you are looking for a solution to a problem you cannot solve, this may not be the site for you.

Hi Vingtoft, and welcome to PPCG!  As it stands, this question would likely be a better fit for StackOverflow.  That said, if you add a win condition (usually [tag:code-golf]), this could make for a good challenge.  In the future, we also recommend running questions through the sandbox before posting here.

Hi, sorry for the violation of community guidelines. Feel free to delete my challenge.

@Vingtoft No worries.  I hope we'll see you again for future challenges.  Incidentally, what you're looking for is probably sorted(set(text.split('\n'))).

Em, the challenge looks ok to me...

Am I missing something or is this just split on newlines and deduplicate?

@Shaggy: I have updated my question. One line can appear multiple times (but never two times in a row), so just deduplicating would not be enough. Sorry for the inadequate initial description.

What is the input? The height and the merged screenshot?

Also, in the example, the first and second lines are identical. What do you mean by saying that the same line can't come twice in a row?

The same line will never come twice in a row in "expected result", but it might occur in input. Yes, window height is known and can be used as input.

so... the input in your example input comprises of 7 blocks (screens) of 5 lines of text? and you are logging the additions from one screen to the other? and the line 1 is repeated because it appears in [5,6,7,8,1]  but not in [4,5,6,7,8] (previous screen) ?

so the output is the result of seven comparisons which in sequence add: [1,2] [3,4] [5] [6] [7] [8] [1 ?]

Hi and welcome to PPCG.  Generally it is frowned upon to change the question after answers have been given, especially if it invalidates existing answers.  I just voted to close due to the question now being unclear. I'll delete my own answer for now, until I can understand exactly what is being asked.

@DigitalTrauma I understand, apologies, this is my first question on this site.

you should post challenges in the sandbox before posting on main site. 2. all challenges must have an objective winning criteria (see [help/on-topic]) . 3. you should absolutely avoid writing posts on this site like help request -- it's a challenge, not a question, not a task, not an assignment. 4. see When is EDIT/UPDATE appropriate in a post? 5. See formatting help, you should format data as code.

@Stephen On editing somebody else's off-topic question to make it on-topic without the owner's word - Programming Puzzles & Code Golf Meta Stack Exchange Instead, tell OP how to edit the post in the comment section.

Japt -R, 11 bytes
This passes the test case but the spec still isn't clear enough
·ò¨ mÌò¦ mg

Try it