Skip to content

Instantly share code, notes, and snippets.

@kamahen
Created October 6, 2023 16:45
Show Gist options
  • Save kamahen/35cdfde14d7dfbfc07ceceb5d97c8cd7 to your computer and use it in GitHub Desktop.
Save kamahen/35cdfde14d7dfbfc07ceceb5d97c8cd7 to your computer and use it in GitHub Desktop.
deadfish code using dict/DCG and library(yall)
% Deadfish is one of the best known non Turing-complete programming languages.
% It has only one accumulator (which starts at 0) to store data, and only four commands:
%
% i - Increment the accumulator
% s - Square the accumulator
% d - Decrement the accumulator
% o - Output the accumulator
%
% Create a program that will input a number and output Deadfish
% code to display the number. It must work for any integer from 0 to 255.
%
% https://codegolf.stackexchange.com/questions/40124/short-deadfish-numbers/
% Using:
% https://swi-prolog.discourse.group/t/dealing-with-state/6866/10
% Op<StateName to operate on the various state variables. Op is one of
%
% List<StateName for a normal DCG terminal
% String<StateName for a SWI-Prolog string acting as a terminal
% Callable<StateName. When found, we call call(Callable, V0, V) to
% update the state for StateName
% :- set_prolog_flag(optimise, true). % For the arithmetic statements
goal_expansion(<(On, Name,State0,State), Clause) :-
expand(On, Name, State0, State, Clause).
expand(Literal,Name,State0,State, Clause), is_list(Literal) =>
Clause = get_dict(Name, State0, List, State, Tail),
append(Literal, Tail, List).
expand(String,Name,State0,State, Clause), string(String) =>
Clause = get_dict(Name, State0, List, State, Tail),
string_codes(String, Literal),
append(Literal, Tail, List).
expand(Step,Name,State0,State, Clause), callable(Step) =>
extend_goal(Step, [V0,V], StepEx),
Clause = ( get_dict(Name, State0, V0, State, V),
StepEx
).
score_deadfish(Score) :-
findall(X, (between(1,255,N),
deadfish_time(N, X)), Xs),
maplist(deadfish_length, Xs, Lens),
sum_list(Lens, Score).
deadfish_length(_Inferences:_N:_Ops:Len:_Cpu, Len).
deadfish_time(N, X) :-
call_time(min_deadfish(N, Ops),T),
length(Ops, Len),
X=T.inferences:N:Ops:Len:T.cpu.
min_deadfish(Num, Ops) :-
between(1, 100000000, OpsLen),
deadfish(Num, OpsLen, Ops),
!.
deadfish(Num, OpsLen, Ops) :-
number_digits(Num, Ds),
State0 = #{acc:0, ops:Ops, output:Ds},
State = #{acc:_, ops:[], output:[]},
call_dcg(seq_of_len(OpsLen, deadfish), State0, State).
seq_of_len(0, _) --> [].
seq_of_len(Len, P) -->
{ Len > 0 },
call(P),
{ Len2 is Len - 1 },
seq_of_len(Len2, P).
:- if(false). % if(true): doesn't use library(yall)
deadfish -->
[s]<ops,
square<acc.
deadfish -->
[i]<ops,
incr<acc.
deadfish -->
[d]<ops,
decr<acc.
deadfish -->
[o]<ops,
value(Acc)<acc,
{ number_digits(Acc, Digits) },
output_digits(Digits).
:- else.
:- use_module(library(yall)).
deadfish -->
[s]<ops,
[S0,S]>>(S is S0**2)<acc.
deadfish -->
[i]<ops,
[S0,S]>>(S is S0+1)<acc.
deadfish -->
[d]<ops,
[S0,S]>>(S is S0+1)<acc.
deadfish -->
[o]<ops,
value(Acc)<acc,
{ number_digits(Acc, Digits) },
output_digits(Digits).
:- endif.
value(V, V, V).
incr(X0, X) :- X is X0 + 1.
decr(X0, X) :- X is X0 - 1.
square(X0, X) :- X is X0 ** 2.
number_digits(Number, Digits) :-
number_codes(Number, Codes),
maplist(code_digit, Codes, Digits).
code_digit(Code, Digit) :-
Digit is Code - 0'0. % '
output_digits([]) --> [].
output_digits([D|Ds]) -->
[D]<output,
output_digits(Ds).
end_of_file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment