:- use_module(library(clpfd)). % den state kannst du mit nem dictoniary modellieren: initState(state{ x: 0, y: 0, z:0, w: 0 , in: I}, I). % Dictonary lookup: initstate(State), R = State.x % Dictonary update: initstate(State), NewState = State.put(x, 1) % Convert List of input digits into single number %input_number(+Inputs, -Number) input_number(Inputs, Number) :- atomic_list_concat(Inputs, Number). % read program helper functions noteof(L) :- \+ L = [end_of_file]. string_term(String,Term) :- term_string(Term, String). parse_instr(String, Inst) :- split_string(String, " ", "", Words), maplist(string_term, Words, Inst). % Read a list of Instructions from Filename % read_program(+Filename, -Prog) read_program(Filename, Prog) :- open(Filename, read, Str), read_string(Str, _, S), split_string(S, "\n", "", Lines), maplist(parse_instr, Lines, Instrs), include(noteof, Instrs, Prog), close(Str). % Takes input and state and binds O to a number num(N,S,O) :- atom(N), O = S.N. num(N,S,O) :- number(N), O = N. eq(A,B,R) :- A = B, R = 1. eq(A,B,R) :- A #\= B, R = 0. read_input(In,F,NIn) :- [F | NIn] = In. % interprets an instruction % interpret(+list,+state,R) interpret([inp, A],InState,OutState) :- read_input(InState.in,C,NInput), BS = InState.put(A,C), OutState = BS.put(in,NInput). interpret([add, A, B],InState,OutState) :- num(B,InState,C), R #= InState.A + C, OutState = InState.put(A,R). interpret([mul, A, B],InState,OutState) :- num(B,InState,C), R #= InState.A*C, OutState = InState.put(A,R). interpret([div, A, B],InState,OutState) :- num(B,InState,C), R #= InState.A div C, OutState = InState.put(A,R). interpret([mod, A, B],InState,OutState) :- num(B,InState,C), R #= InState.A mod C, OutState = InState.put(A,R). interpret([eql, A, B],InState,OutState) :- num(B,InState,C), eq(InState.A, C, R), OutState = InState.put(A,R). rprogram(State,[],O) :- O = State.z. rprogram(State,[I|Instr], O) :- interpret(I,State,Out), rprogram(Out,Instr,O). program(Instr,Input) :- length(Input, 14), Input ins 1..9, initState(S,Input), rprogram(S,Instr, O), O = 0. max_monad(M) :- read_program(input24,Instr), program(Instr,R), labeling([max,down],R), input_number(R,M), write(M). min_monad(M) :- read_program(input24,Instr), program(Instr,R), labeling([min],R), input_number(R,M), write(M).