27
\$\begingroup\$

Sandbox, Codidact

A rewrite of this question with a simpler input format and guidelines.

Challenge

Deadfish uses a single accumulator, on which all commands are to be performed.

It has the following commands:

Command Description
i increment the accumulator
d decrement the accumulator
s square the value of the accumulator
o output the value of the accumulator as a number

The accumulator starts with a value of zero. If, after executing a command, the accumulator is equal to -1 or equal to 256, the accumulator must be reset to zero.

I/O

Input can be taken as a single string, list of codepoints, or any other reasonable format. It is guaranteed that the input will only consist of deadfish commands.

Output can be given as an array of numbers, or just the numbers printed with separators between them.

Testcases

(some are borrowed from the Esolangs wiki)

iissso -> 0
diissisdo -> 288
iissisdddddddddddddddddddddddddddddddddo -> 0
isssoisoisoisoiso -> 1,4,25,676,458329
ooooosioiiisooo -> 0,0,0,0,0,1,16,16,16
iiii -> nothing
iiiiiiiissdiiiiiiiiiiiiiiiiio -> 4112
o -> 0

Without Outputs

\$\endgroup\$
12
  • \$\begingroup\$ Can there be leading separators? \$\endgroup\$
    – att
    Jan 30 at 22:41
  • \$\begingroup\$ What if the accumulator exceeds 256? For example, 29^2? \$\endgroup\$
    – Xcali
    Jan 31 at 1:12
  • 3
    \$\begingroup\$ @Xcali the checks are only for -1 or 256, so nothing should happen in that case. \$\endgroup\$
    – Razetime
    Jan 31 at 2:09
  • 2
    \$\begingroup\$ @tsh As long as it satisfies the testcases, it is fine. The accumulator will stay within the maximum integer range of your language. \$\endgroup\$
    – Razetime
    Jan 31 at 3:44
  • 1
    \$\begingroup\$ diso tests every functionality of the code except for 256 \$\endgroup\$
    – Gotoro
    Jan 31 at 14:52

46 Answers 46

1
2
2
\$\begingroup\$

Java (JDK), 98 bytes

s->{int a=0;for(var c:s){if((c%=7)>5)System.out.println(a);a=c%5<3?1-c%5+a:a*a;a=a<0|a==256?0:a;}}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Lua (LuaJIT), 153 151 bytes

t={}v=0;loadstring(s:gsub('.',{d='v=v-1;',i='v=v+1;',s='v=v*v;',o='t[#t+1]=v;'}):gsub(';',';v=(v==256 or v<0)and 0 or v;'))()print(table.concat(t,','))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Yabasic, 119 115 bytes

a=0
for j=1 to len(i$)
c=instr("isdo",mid$(i$,j,1))
if c<4 a=a+2-c
if c=2 a=a*a
if c=4 ?a;
if a<0 or a=256 a=0
next

Try it online!

The actual input is done via reading DATA statements for each Deadfish program. For an interactive version I'd just replace that with an INPUT i$ statement, and calling RUN at the end should re-run the program, initializing variables to 0 and removing the need for the a=0 statement.

I feel this could be more compact, but everything else I try actually makes it bigger. The only really "golf-y" thing is the line:

if c<4 a=a+2-c

which for command 2=square has no effect, avoiding the need for one IF evaluation and saving 11 bytes vs the more straightforward implementation.

Even the XOR 256 trick works out identical in length to the more straightforward version above so I stuck with the simpler code.

edit - I did save 4 bytes because the BASIC interpreter I'm using puts a space as a seperator between numbers automatically, so no need to add it.

\$\endgroup\$
2
\$\begingroup\$

Julia, 70 bytes

s->(a=0;!c=a=[a*=a⊻256>0,a-1,a*a,a+1,c%5>0&&print(a,-)][c÷2%6];.!s)

Based on ovs's answer

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Vyxal DO, 25 bytes

0Ȯ(n«ƛ√J«`›‹²…`ĿĖ:₈u"=a[0

Try it Online!

Saved a byte thanks to Aaron Miller.

0                         # Push 0
 Ȯ(n                      # Iterating over the input
    «ƛ√J«`›‹²…`Ŀ          # Transliterate into appropriate Vyxal instruction
                Ė         # Evaluate
                 :₈u"=a[  # If 256 or negative
                        0 # Push 0
\$\endgroup\$
1
2
\$\begingroup\$

Perl 5 -F -E, 96 91 90 79 74 bytes

(+4 bytes for switches included)

Saved 5 bytes by using a built-in variable that defaults to 0 ($- / $FORMAT_LINES_LEFT) instead of $a
Saved 1 byte by using print and $/ instead of CORE::say
Saved 11 bytes by using -F and -E switches
Saved 4 bytes by (ab)using regex match return value coercion. Saved 0 bytes but improved readability by changing $- to $% ($FORMAT_PAGE_NUMBER)

for(@F){$%+=/i/;$%-=/d/;$%*=$%if/s/;say$%if/o/;$%=0if$%=~/^(-1|256)$/}

Try it online!

More-readable version:

for (@F) {
    $% += /i/;
    $% -= /d/;
    $% *= $% if /s/;
    say($%) if /o/;
    $% = 0 if $% =~ /^(-1|256)$/;
}
\$\endgroup\$
1
\$\begingroup\$

Icon, 106 bytes

procedure f(s);a:=0
c:=!s&(if a:=[a+1,a-1,a*a][find(c,"ids")]then 1>ixor(a,256)&a:=0 else write(a))&\z
end

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 118 bytes

$args[0]|% t*y|%{if($a-in@(-1,256)){$a=0}if($_-eq'i'){$a+=1}elseif($_-eq'd'){$a-=1}elseif($_-eq's'){$a=$a*$a}else{$a}}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Batch, 157 bytes

@set a=0
@for %%c in (%*) do @call:%%c
:s
@set/aa=a*a-1
:i
@set/aa+=2
:d
@set/aa-=1
@if %a%==-1 set a=0
@if %a%==256 set a=0
@exit/b
:o
@echo %a%

Takes each Deadfish command as a separate command-line argument. Explanation:

@set a=0

Initialise the accumulator.

@for %%c in (%*) do @call:%%c

Loop through all of the commands, executing each in turn, then fall through into performing an additional s command, whose effect is non-observable.

:s
@set/aa=a*a-1

For the s command, square the accumulator and decrement it, then fall through to the i command, which increments it again.

:i
@set/aa+=2

For the i command, add 2 to the accumulator, then fall through to the d command, which decrements it.

:d
@set/aa-=1

For the d command, decrement the accumulator.

@if %a%==-1 set a=0
@if %a%==256 set a=0
@exit/b

Adjust the accumulator if necessary, then return for the next command.

:o
@echo %a%

For the o command, output the accumulator, then implicitly return for the next command.

204 bytes taking input as a single string (probably actually not the best approach; the call-and-fall through approach above could probably save 10 bytes):

@set/ps=
@set a=0
:l
@if "%s%"=="" exit/b
@for %%a in (1+1.i 1-1.d a.s)do @if %%~xa==.%s:~,1% set/aa=a*%%~na
@if %s:~,1%==o echo %a%
@set s=%s:~1%
@if %a%==-1 set a=0
@if %a%==256 set a=0
@goto l

Takes input on STDIN. Explanation:

@set/ps=
@set a=0

Read the commands and clear the accumulator.

:l
@if "%s%"=="" exit/b

Loop until there are no commands left.

@for %%a in (1+1.i 1-1.d a.s)do @if %%~xa==.%s:~,1% set/aa=a*%%~na

If the command is an arithmetic operation then perform the calculation: a=a*1+1 for i, a=a*1-1 for d and a=a*a for s; it's not possible to use * in a for loop because it's always a wildcard and cannot be quoted (unlike =, which can be quoted).

@if %s:~,1%==o echo %a%

If the command is an o then output the accumulator.

@set s=%s:~1%

Remove the command from the input.

@if %a%==-1 set a=0
@if %a%==256 set a=0
@goto l

Adjust the accumulator if necessary and loop.

\$\endgroup\$
1
\$\begingroup\$

Racket, 178 bytes

(define(f s[a 0])(unless(null? s)(let([x(car s)][y(cdr s)][b(match a[-1 0][256 0][_ a])])(match x[105(f y(+ b 1))][100(f y(- b 1))][115(f y(* b b))][_(and(writeln b)(f y b))]))))

Try it online!

More readable:

(define (f s [a 0])
  (unless (empty? s)
    (let ([x (first s)]
          [y (rest s)]
          [b (match a
               [-1  0]
               [256 0]
               [_   a])])
      (match x
        [105 (f y (+ b 1))]
        [100 (f y (- b 1))]
        [115 (f y (* b b))]
        [_   (and (writeln b)
                  (f y b))]))))
\$\endgroup\$
1
\$\begingroup\$

R, 111 91 bytes

-20 bytes thanks to CriminallyVulgar

C=scan(,'');n=0;for(x in C){if(n%in%c(-1,256))n=0;n=switch(x,i=n+1,d=n-1,s=n^2,o=print(n))}

Try it online!

\$\endgroup\$
1
1
\$\begingroup\$

Vyxal, 28 bytes

❝,(\&`\⨥\⨪\²\₴`ni+ₑuγd‿¥c[0£

Try it Online!

Takes a list of numbers, where 0 represents i, 1 represents d, 2 represents s and 3 represents o

\$\endgroup\$
1
  • \$\begingroup\$ @2x-1 that's a result of the safe-evaluation regex I have in place \$\endgroup\$
    – lyxal
    Mar 1 at 3:56
1
\$\begingroup\$

Pip, 39 bytes

Fca;V("U  i&D SQ:   P"^sAc)."i*:i!=256"

Takes the Deadfish program as a command-line argument. Try it here! Or, here's a 42-byte version in Pip Classic: Try it online!

Explanation

The variable i is preset to 0, so we'll use it for the accumulator.

Fca;V("U  i&D SQ:   P"^sAc)."i*:i!=256"
Fca;                                     For each c in command-line argument a:
      "U  i&D SQ:   P"                    Take this string
                      ^s                  Split on spaces into a list of 7 strings
     (                    )               Index (0-based, modular) into that list using
                        Ac                the ASCII code of c
                           .              Concatenate
                            "i*:i!=256"   this string
    V                                     Eval as Pip code

The code snippets for each command are:

i -> index 0 -> Ui*:i!=256
d -> index 2 -> i&Di*:i!=256
s -> index 3 -> SQ:i*:i!=256
o -> index 6 -> Pi*:i!=256

The first three expressions change the value of i and then multiply it by 0 if the new value equals 256:

Ui    Increment i
i&Di  If i is not 0, decrement i
SQ:i  Square i in place

The fourth expression parses a little differently: since P is lower precedence than assignment, it works out to "multiply i by 0 if it equals 256, and then print." Fortunately, since printing doesn't change the value of i, the order doesn't matter.

\$\endgroup\$
1
\$\begingroup\$

Swift, 120 bytes

{(s:String)in var i=0
s.forEach{switch $0{case"i":i+=1 case"d":i-=1 case"s":i*=i default:print(i)}
if i==256||i<0{i=0}}}

Returns a closure that takes the input as an argument. If the input contains o multiple times, the numbers are separated by newlines.
Try it online (full program that uses hardcoded input)

Ungolfed:

{ (str: String) in
    var i = 0
    str.forEach { (char: Character) in
        switch char {
        case "i":
            i += 1
        case "d":
            i -= 1
        case "s":
            i *= i
        default: // "o"
            print(i)
        }
        
        if i == 256 || i < 0 {
            i = 0
        }
    }
}
\$\endgroup\$
1
\$\begingroup\$

TI-Basic, 83 bytes

Input Str1
For(I,1,length(Str1
inString("ids",sub(Str1,I,1→J
If Ans:Then
{A+1,A-1,A²
Ans(J
max(0,Ans)(Ans≠256→A
Else
Disp A
End
End

Input is taken as a string and outputs are printed and separated with newlines.

\$\endgroup\$
0
\$\begingroup\$

Batch 160 bytes

@Set v=0&@Set i=v+=1&@Set d=v-=1&@Set s=v*=v&2>nul (@For %%i in (%*)Do @Set/A"-1/(v+1)"||Set v=0&Set/A"256/(v-256)"||Set v=0&Call Set/A%%%%i%%||Call Echo(%%v%%)

How? :

  • & = concatenate commands
  • @Set v=0 = Zero accumulator value
  • Set i=v+=1 ; Set d=v-=1 ; Set s=v*=v = Defines operation to perform when command parameters parsed
  • For %%i in (%*)Do = Iterate over command parameters
  • @Set/A"-1/(v+1)"||Set v=0 = Conditional assesment of accumalator if value EQU -1 (Set /A opeations fails due to divide by zero error)
  • Set/A"256/(v-256)"||Set v=0 = Conditional assesment of accumalator if value EQU 256 (Set /A opeations fails due to divide by zero error)
  • Call Set/A%%%%i%%|| = expands to the defined command arg operation or FAILS for the undefined o command (Missing operator), triggering || execution of Call Echo(%%v%%
    • Call triggers additional parsing steps for the subsequent command, allowing a variable named with %%I's value to be expanded, without having to resort to using delayed expansion.
  • 2>nul (For ...) redirection used to suppress STDERR resulting from operations with missing operators or that divide by zero
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.