Created
October 6, 2023 16:45
-
-
Save kamahen/35cdfde14d7dfbfc07ceceb5d97c8cd7 to your computer and use it in GitHub Desktop.
deadfish code using dict/DCG and library(yall)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% 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