35
\$\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\$
14
  • \$\begingroup\$ Can there be leading separators? \$\endgroup\$
    – att
    Commented Jan 30, 2021 at 22:41
  • \$\begingroup\$ What if the accumulator exceeds 256? For example, 29^2? \$\endgroup\$
    – Xcali
    Commented Jan 31, 2021 at 1:12
  • 4
    \$\begingroup\$ @Xcali the checks are only for -1 or 256, so nothing should happen in that case. \$\endgroup\$
    – Razetime
    Commented Jan 31, 2021 at 2:09
  • 3
    \$\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
    Commented Jan 31, 2021 at 3:44
  • 1
    \$\begingroup\$ diso tests every functionality of the code except for 256 \$\endgroup\$
    – Gotoro
    Commented Jan 31, 2021 at 14:52

60 Answers 60

16
\$\begingroup\$

flex, 86 \$\cdots\$ 83 82 bytes

Saved 2 bytes and got moved into TIO thanks to Mukundan314!!!

%{
a;m(){a*=a!=256;}
%}
%%
i m(++a);
d m(a&&--a);
s m(a*=a);
o printf("%d ",a);
%%

Try it online!

flex stands for fast lexical analyser generator. It takes input as above and generates a lexer in C.

The input comprises of a C declaration section:

%{
a;m(){a*=a!=256;}
%}

where here we simply declare the accumulator a (implicitly as an int) and a function to set the accumulator to \$0\$ if it's \$256\$ after a computation.

This is followed by the rules section comprised of all the regexes that need to be parsed along with their actions (in C):

%%
i m(++a);
d m(a&&--a);
s m(a*=a);
o printf("%d ",a);
%%   

here we have our 4 characters along with the code to run when each is encountered. Decrement will only happen if the accumulator is non-zero.

There's a program section that follows this but it will simply default to a main that runs the parser if left out (as in this case).

You can generate the C-source code lexer from the above (in file deadfish.l) and compile it with the following:

flex deadfish.l
gcc lex.yy.c -o deadfish -lfl  

After compiling, running the following:

echo iissso | ./deadfish
echo diissisdo | ./deadfish
echo iissisdddddddddddddddddddddddddddddddddo | ./deadfish
echo isssoisoisoisoiso | ./deadfish
echo ooooosioiiisooo | ./deadfish
echo iiiiiiiissdiiiiiiiiiiiiiiiiio | ./deadfish  

outputs:

0
288
0
1 4 25 676 458329
0 0 0 0 0 1 16 16 16
4112   

You can also just run it as ./deadfish and have an interactive deadfish environment to play with to your heart's content!

\$\endgroup\$
4
  • \$\begingroup\$ 84 bytes \$\endgroup\$ Commented Jan 31, 2021 at 13:49
  • \$\begingroup\$ @Mukundan314 Nice one + thanks for getting it working in TIO! :D \$\endgroup\$
    – Noodle9
    Commented Jan 31, 2021 at 13:58
  • \$\begingroup\$ Why is the header linking to GNU Bash? \$\endgroup\$
    – Wezl
    Commented Feb 2, 2021 at 19:08
  • \$\begingroup\$ @Wezl Because TIO doesn't handle flex directly but you can run via bash. \$\endgroup\$
    – Noodle9
    Commented Feb 2, 2021 at 19:46
14
\$\begingroup\$

JavaScript (ES10), 66 bytes

Expects a list of codepoints.

a=>a.flatMap(n=>n%5?p:(p=(p=[p-!!p,p+1,,p*p][n&3])-256&&p,[]),p=0)

Try it online!

How?

o is the only command whose codepoint (\$111\$) modulo \$5\$ is not equal to \$0\$. This is also the only command that requires a special operation that doesn't update the accumulator. That's why we first test that.

If the first modulo is \$0\$, we apply a modulo \$4\$ to distinguish between the other commands and update the accumulator accordingly.

 char. | code | mod 5 | mod 4
-------+------+-------+-------
  'd'  |  100 |   0   |   0
  'i'  |  105 |   0   |   1
  'o'  |  111 |   1   |  (3)
  's'  |  115 |   0   |   3
\$\endgroup\$
0
11
\$\begingroup\$

convey, 90 76 bytes

 {"='i'
0+#<
^v"='d'
^-#<
^v"='s'
^*#+1
^.=<'o'
^>@`
^}",
*<<"=256
.="*.
0-1

Try it online!

On the top right side, the input gets compared with idso. The result (0 or 1) then gets combined with the accumulator: a += c == 'i', a -= c == 'd', a = pow(a, (c == 's') + 1) (pow = *.), and o pushes a copy into the output @"}. At the bottom are the checks for -1/256, by calculating a *= a != 256 and a *= a != -1. Then the accumulator loops back to start the next round.

One iteration of the accumulator loop:

one iteration

\$\endgroup\$
10
\$\begingroup\$

Ruby, 60 58 bytes

Saved 2 bytes thanks to @Sisyphus

a=0;$<.bytes{|b|a=0if(a=eval'~-~p a*'[b%20/3,2]+?a)^256<1}

Try it online or verify all test cases.

Full program that reads a string from STDIN and outputs to STDOUT, one number per line.

Each operation on the accumulator a is carried out by evaling a 3-byte string. The third byte is always a. The first two bytes are extracted from the string ~-~p a* starting at index b%20/3:

Op \$b\$ \$\left\lfloor\frac{b\bmod20}{3}\right\rfloor\$ eval
d \$100\$ \$0\$ ~-a
i \$105\$ \$1\$ -~a
o \$111\$ \$3\$ p a
s \$115\$ \$5\$ a*a

The reset conditions on the accumulator, which might be written a==-1||a==256 in ungolfed form, are replaced by the single condition a^256<1 (^ is bitwise XOR) because negative accumulator values other than \$-1\$ are not possible.

\$\endgroup\$
2
  • \$\begingroup\$ This is really nice - I especially like how you use the - twice. It's two bytes shorter as a full program: Try it online! \$\endgroup\$
    – Sisyphus
    Commented Jan 31, 2021 at 6:34
  • \$\begingroup\$ @Sisyphus Nice one, thank you. I feel like $< tends to fly under my global variable radar! \$\endgroup\$
    – Dingus
    Commented Jan 31, 2021 at 9:32
10
\$\begingroup\$

Python 2, 83 82 76 74 bytes

Thanks to dingledooper for spotting a bug and -6 bytes!
-2 bytes thanks to Mukundan!

Takes input as a list of codepoints.

a=0
for x in input():
 a=[a-1,a+1,a,a*a][x/6%4];a*=a^256>0
 if x%5:print a

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I think it should be [a-1,a+1,a,a*a] instead of [a-1,a+1,a*a,a]. \$\endgroup\$ Commented Jan 31, 2021 at 1:47
  • \$\begingroup\$ @dingledooper You're right, thanks a lot. Now fixed and all test cases included. \$\endgroup\$
    – ovs
    Commented Jan 31, 2021 at 8:07
  • 1
    \$\begingroup\$ And here's a 6 byte improvement \$\endgroup\$ Commented Jan 31, 2021 at 8:24
  • \$\begingroup\$ @dingledooper I used a+a%~a before, but completely missed that it was possible here, thanks again. \$\endgroup\$
    – ovs
    Commented Jan 31, 2021 at 8:32
  • 1
    \$\begingroup\$ 74 bytes \$\endgroup\$ Commented Feb 1, 2021 at 2:32
8
\$\begingroup\$

Nim, 104 bytes

var r=0
for c in stdin.readAll:
 r=[r*r,r,r+1,r-1][28-c.ord div 4];r*=int (r xor 256)>0;if c=='o':echo r

Try it online!

Based on @ovs's amazing Python answer.

Nim, 120 114 109 bytes

var r=0
for c in stdin.readAll:
 case c
 of'i':r+=1
 of'd':r-=1
 of's':r*=r
 else:r.echo
 if r in[-1,256]:r=0

Try it online!

This is embarassingly readable.

-5 bytes by taking inspiration from @Gotoro's Python answer

\$\endgroup\$
7
\$\begingroup\$

Python 3, 120 95 bytes

n=0
for x in input():
	if n in(-1,256):n=0
	if"o"==x:print(n)
	else:n=[n+1,n-1,n*n][ord(x)%4^1]

Try it online!

Brought it down by 25 bytes thanks to Danis suggestion!

Using bit manipulation ^ we choose from the list of possible operations. Original suggestion used ord(x)%4^2 which yielded 0,1,2,3 for indexes and required the use of an additional 0 in the list at the index 0;

using ^1 instead yields 0,1,2, which allows to save 2 bytes in comparison.

Maybe it is possible to account for that additional 0 and use it as a condition to print o instead.(?)

\$\endgroup\$
9
  • 3
    \$\begingroup\$ Welcome to PPCG! You can save 10 bytes by making it a full program and 1 byte by changing a**=2 to a*=a: Try it online! \$\endgroup\$
    – xigoi
    Commented Jan 30, 2021 at 22:58
  • 1
    \$\begingroup\$ 116 bytes \$\endgroup\$ Commented Jan 30, 2021 at 23:52
  • 2
    \$\begingroup\$ @Danis your suggestion doesn't work, as else in the end only connects to if "s", which will output an answer every time it is not an "s". I've added elifs to it, bringing it down to 106 bytes in the end, thank you! \$\endgroup\$
    – Gotoro
    Commented Jan 31, 2021 at 7:34
  • 3
    \$\begingroup\$ 86 bytes \$\endgroup\$ Commented Jan 31, 2021 at 11:30
  • 3
    \$\begingroup\$ 80 bytes based on Mukundan's suggestion. This uses the way chained comparisons are evaluated to get rid of the if/else statement. \$\endgroup\$
    – ovs
    Commented Jan 31, 2021 at 14:49
6
\$\begingroup\$

><>, 81 bytes

Not the dead one :)

0v~$?$0+{="Ā":}=-10<
l<n:oav?="i"{v?="d"}:{v?="s"}:{;?=1
{~:*1->  2+0}>{~1-:v  >

Try it online!

Branching is the kryptonite of ><> terseness, so the golfiness here was creating a branchless -1 and 256 check ~$?$0+{="Ā":}=-10 backwards on the first line to get rid of whitespace. The s, i and d commands also feed into each other to make the layout manageable.

\$\endgroup\$
5
\$\begingroup\$

C (gcc), 92 91 bytes

Thanks to ceilingcat for the -1.

Converts each operation into the range [0,3] to simplify the decoding process.

a,b;f(char*s){for(a=0;b=*s++/2;a*=a-256&&~a)(b&=3)?--b?--b?printf("%i ",a):a--:(a*=a):a++;}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ 82 bytes :-) \$\endgroup\$
    – jdt
    Commented Aug 27, 2021 at 14:15
4
\$\begingroup\$

Wolfram Language (Mathematica), 60 bytes

Fold[<|i->#+1,d->#-1,s->#^2,o:>Echo@#|>@#2/.-1|256->0&,0,#]&

Try it online!

Input a list of symbols.

\$\endgroup\$
4
\$\begingroup\$

AWK, 55 53 52 51 bytes

Thanks to user41805 for removing awk flags

Expects each operation to be on a separate line

{a*=a!=256}/i/{a++}/d/{a&&a--}/s/{a*=a}/o/{print+a}

Try it online!

Explanation

{a*=a!=256}    # Before each operation multiply a by 0 if it equals 256
/i/{a++}       # If line contains 'i' increase a by 1
/d/{a&&a--}    # If line contains 'd' and a is non-zero decrement a by 1
/s/{a*=a}      # If line contains 's' square a
/o/{print+a}   # If line contains 'o' output a
\$\endgroup\$
4
  • \$\begingroup\$ Ah, I see, Awk uses doubles so they would end up at infinity. \$\endgroup\$
    – EasyasPi
    Commented Jan 31, 2021 at 3:29
  • \$\begingroup\$ Nice! Feeding the commands separated by "\n" was a good idea. I think you need to move the first clause (the 0/256) check to after the "s" code and before the "o" code though. Otherwise it might print "-1" or "256" if the operations are lined up just right. \$\endgroup\$
    – cnamejj
    Commented Jan 31, 2021 at 8:02
  • \$\begingroup\$ @cnamejj That would only be a problem if the operators were not separated by a newline \$\endgroup\$ Commented Jan 31, 2021 at 8:14
  • 1
    \$\begingroup\$ You can remove the flags if you use print+a at the end \$\endgroup\$
    – user41805
    Commented Jan 31, 2021 at 9:54
4
\$\begingroup\$

MathGolf, 23 bytes

0ÿ)²(o▒꽧"_♠bαm¡╓*"u~╘

Input as a list of codepoint integers.

Try it online.

Explanation:

0                       # Start with 0
 ÿ)²(o                  # Push 4-char string ")²(o"
      ▒                 # Convert it to a list of characters: [")","²","(","o"]
       ê                # Push the input-list of codepoint integers
        ½               # Integer-divide each by 2
         §              # Index (modulair 0-based) them into the list of characters
          "_♠bαm¡╓*"u   # Join these characters with "_♠bαm¡╓*" delimiter
                     ~  # Execute the entire string as MathGolf code
                      ╘ # Discard everything left on the stack (which otherwise would be
                        # output implicitly)

  )                     # Increase by 1
   ²                    # Square
    (                   # Decrease by 1
     o                  # Print without popping

           _            # Duplicate the top of the stack
            ♠bα         # Push 256, push -1, wrap them in a list: [256,-1]
               m        # Map over both of them:
                ¡       #  And check that they're NOT equal to the value we've duplicated
                        #  (0 if the duplicated value is -1 or 256; 1 otherwise)
                 ╓      # Pop and get the minimum of this list
                  *     # Multiply it to the value
\$\endgroup\$
4
\$\begingroup\$

05AB1E, 23 22 21 bytes

-1 -2 bytes thanks to Command Master!

Takes input as a list of codepoints.

õ?Îv">n<="y;è.VD₁^0›*

Try it online!

Commented:

õ?                  # print the empty string without a trailing newline
                    # this is necessary to disable implicit output if no 'o' is in the code
  Î                 # push 0 and the input
   v                # iterate over the instructions y in the input:

">n<="              # push string literal ">n<="
                    # These are the instructions in 05AB1E equivalent to "isdo"
      y             # push the current instruction
       ;            # halve the instruction
        è           # modular index into the instruction string
          .V        # execute the instruction
            D       # duplicate the current value
             ₁^     # XOR with 256
               0›   # is this larger than 0?
                 *  # multiply the result with the current value
                    # x*(x^256>0) maps negative numbers and 256 to 0
\$\endgroup\$
2
4
\$\begingroup\$

Rust, 119 bytes

Closure with a single parameter of type Iterator<Item = u8> with ASCII bytes

|s|{let mut a=0;for c in s{a=match c{105=>a+1,100=>a-1,115=>a*a,111=>{println!("{}",a);a},_=>a};if a==-1||a==256{a=0}}}

Try it online! (with caller function)

Ungolfed version

|s|{
    let mut a = 0;
    for c in s {
        a = match c {
            105 => a + 1,
            100 => a - 1,
            115 => a * a,
            111 => { println!("{}", a); a },
            _ => a
        };
        if a == -1 || a == 256 { a = 0 }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Suggest if-1==a instead of if a==-1 \$\endgroup\$
    – ceilingcat
    Commented May 17, 2021 at 4:50
4
\$\begingroup\$

x86-16 machine code, 45 43 bytes

Source-compatible with x86 and x86_64.

Fails one test due to integer overflow, but instructions are given to switch it to 64-bit arithmetic in the demo.

00000000: 31 d2 ac 3c 64 72 23 74 0d 3c 69 74 0c 3c 6f 92  1..<dr#t.<it.<o.
00000010: 74 0a f7 e0 eb 07 4a eb 05 42 eb 02 ab 92 85 d2  t.....J..B......
00000020: 78 de 81 fa 00 01 74 d8 eb d8 c3                 x.....t....

        // "//" comments are solely for syntax highlighting
        // sed -i -e 's#//#;#g' deadfish.asm
        // nasm compatible
        [bits 16]
        [cpu 8086]
        global deadfish
        // Input:
        //    si: input, null terminated string
        //    di: output, uint16_t array
        // Output:
        //
        //    di: points past the last value in the array
deadfish:
.Lzero:
        // Set accumulator to 0
        xor     dx, dx
.Lloop:
        // Load byte
        lodsb
        // Check for null terminator and for 'd'
        cmp     al, 'd'
        // Below means null terminator, return
        jb      .Lret
        // equal means 'd'
        je      .Lop_d
        // check for 'i'
        cmp     al, 'i'
        je      .Lop_i
        // check for 'o'
        cmp     al, 'o'
        // Since O and S both need AX instead of DX, xchg here.
        xchg    dx, ax
        je      .Lop_o
        // assume 's'
.Lop_s:
        // Square
        mul     ax
        // Jump to the end of the o code to swap AX to DX.
        jmp     .Lnext_xchg
.Lop_d:
        // Decrement
        dec     dx
        jmp     .Lnext
.Lop_i:
        // Increment
        inc     dx
        jmp     .Lnext
.Lop_o:
        // Output
        // *di++ = ax
        stosw
        // Swap dx and ax again for o and s
.Lnext_xchg:
        xchg    dx, ax
.Lnext:
        // Check for -1 (less than zero) and 256
        // If equal, jump to the xor dx, dx conveniently placed before the loop
        test    dx, dx
        js      .Lzero
        // Literally the only reason I am using 16-bit is this instruction :P
        cmp     dx, 256
        je      .Lzero
        // Otherwise, jump to the top of the loop
        jmp     .Lloop
.Lret:
        // Return
        ret

The input is a null terminated string in si, and the output is stored to the uint16_t array in di.

di will point to the end of the array to indicate the length (C++ <algorithm> style)

Try it online! Uses GAS Intel syntax because I want to use libc with it, and uses macros for registers to make it possible to switch to 64-bit arithmetic.

\$\endgroup\$
4
\$\begingroup\$

J, 64 58 bytes

g=:]e.&256 _1|]
i=:g>:
d=:g<:
s=:g*:
o=:1!:2&2
f=:'0'".@|.@,]

Try it online!

-6 thanks to FrownyFrog!

Note: -3 off TIO count for f=:

This stores each Deadfish command in a variable of the same name, followed by the -1/256 check. Then we just prepend 0, reverse, and eval.

Takes input with spaces between the letters.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ ���6 \$\endgroup\$
    – FrownyFrog
    Commented Aug 31, 2021 at 2:28
  • \$\begingroup\$ Very nice idea! \$\endgroup\$
    – Jonah
    Commented Aug 31, 2021 at 2:43
3
\$\begingroup\$

Retina, 61 bytes

\bi()|#?\bd|^(#*)s
$#1*#$.2*$2
^#{256}\b

m}`^(#*)o
$.1¶$1
#

Try it online! Link includes test cases, although they can be a bit slow (I think #?\bd is the slow case, but I'm not sure). Explanation:

\bi()|#?\bd|^(#*)s
$#1*#$.2*$2

Handle the i, d and s cases by inserting a # (for the i case), deleting an optional # (for the d case, also handling a d of 0) or squaring the number of #s (for the s case).

^#{256}\b

But if the value is exactly 256, then set it back to 0 (assuming that there's another operation, otherwise the remaining #s are ignored anyway).

^(#*)o
$.1¶$1

Handle the o case by prepending a decimal copy of the current number of #s on a previous line.

m}`

Evaluate the above stages until there are no more letters to process; also turn on multiline matching for all of the stages.

#

Delete any remaining accumulated unary value.

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 37 bytes

≔⁰θFS«F№⟦²⁵⁶±¹⟧θ≔⁰θ≡ιi≦⊕θd≦⊖θs≧X²θ⟦Iθ

Try it online! Link is to verbose version of code. Explanation:

≔⁰θ

Initialise the accumulator to 0.

FS«

Loop over the commands.

F№⟦²⁵⁶±¹⟧θ

If the list (256, -1) includes the accumulator...

≔⁰θ

... then set the accumulator to 0. (This is done before the operation because it's golfier, and doesn't change the result, since it still always happens between two operations, and whether it happens after the last operation isn't observable.)

≡ι

Switch on the current operation: ...

i≦⊕θ

... i means increment the accumulator; ...

d≦⊖θ

... d means decrement the accumulator; ...

s≧X²θ

... s means square the accumulator; ...

⟦Iθ

... otherwise print the accumulator on its own line.

\$\endgroup\$
3
\$\begingroup\$

Jelly, 25 24 bytes

:4ị⁾’‘;⁾Ṅ²¤j“-,⁹¤i¬×Ʋ”VZ

Try it online!

Interprets a Deadfish program given as a list of codepoints in a command-line argument, printing newlines between the numbers, then crashes with a TypeError.

Without the last two characters, it's a Deadfish to Jelly transpiler.

Explanation

:4ị⁾’‘;⁾Ṅ²¤j“-,⁹¤i¬×Ʋ”VZ   Main monadic link
:4                         Integer divide by 4
  ị                        Index into
   ⁾’‘;⁾Ṅ²¤                  "’‘Ṅ²"
    ’                          Decrement
     ‘                         Increment
        Ṅ                      Print with newline
         ²                     Square
           j               Join with separator
            “-,⁹¤i¬×Ʋ”       "-,⁹¤i¬×Ʋ"
             -,⁹¤              [-1, 256]
                 i             Find 1-based index
                  ¬            Negate
                   ×           Multiply by the number
                    Ʋ          Group this into one instruction
                      V    Evaluate (implicitly starting with 0)
                       Z   Zip — a number can't be zipped,
                           so this crashes the program in order to
                           suppress the implicit output
\$\endgroup\$
2
  • 2
    \$\begingroup\$ -1 byte? \$\endgroup\$ Commented Jan 30, 2021 at 23:41
  • \$\begingroup\$ @cairdcoinheringaahing Unfortunately that doesn't work, because we need to return 0 (not 1 or 2) when the number is in the list. \$\endgroup\$
    – xigoi
    Commented Jan 31, 2021 at 10:19
3
\$\begingroup\$

Arturo, 80 bytes

$[p][r:0loop p'c[do[[r:r*r][print r][r:r+1][r:r-1]]\28-c/4if or? r<0r=256[r:0]]]

A function that takes an array of codepoints and prints numbers separated by newlines.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I'm looking forward to the moment when arturo-lang.io will be working. \$\endgroup\$ Commented Feb 2, 2021 at 13:14
  • 1
    \$\begingroup\$ @GalenIvanov Yeah, me too. \$\endgroup\$
    – xigoi
    Commented Feb 2, 2021 at 13:15
  • \$\begingroup\$ BTW, do you use Red or Rebol? \$\endgroup\$ Commented Feb 2, 2021 at 13:19
  • \$\begingroup\$ @GalenIvanov I looked at Red and found it interesting, but I've never used it. \$\endgroup\$
    – xigoi
    Commented Feb 2, 2021 at 13:25
  • \$\begingroup\$ OK, thank you, xigoi! \$\endgroup\$ Commented Feb 2, 2021 at 13:30
3
\$\begingroup\$

Husk, 26 25 bytes

tGF₅0hx'o
S&≠256!ë→a□?←0c

Try it online!

Explanation

The first line is the main program, the second line an helper function that computes the output of a Deadfish command that could be 'i', 'd' or 's'.

Let's start from the first line:

tGF₅0hx'o
      x'o    Split the string on each 'o'
     h       and discard the last part 
              (we don't care what happens after the last 'o')
 G  0        Scan this list of strings using 0 as initial value
  F₅          computing the result of each Deadfish subprogram
t            Discard the first value (0)

What we are doing here is splitting the Deadfish code into the subprograms preceding each output 'o', and then computing the result of each subprogram.

The result of a subprogram is computed by folding the helper function over the commands: the fold will start with the value of the accumulator coming from the previous subprogram (initially 0), and will apply the helper function to the next command and the accumulator to generate the new value for the accumulator.

Lines in a Husk program are zero-indexed and modular: referring to line here is effectively the same as referring to line , but the number of times we "loop around" back to the first line determines how the called function should be modified (in order argdup,flip,map,zip,hook); in this case we loop around 2 times, so we flip the helper function, passing the command ('i','d',or 's') first, and the accumulator second.

We chain together the interpretations of the subprograms by scanning over the list of subprograms. A scan G is the same thing as a fold F, except it returns all partial results instead of only the final one. We explicitly set 0 as the initial value, but then the result of each subprogram will be passed as the accumulator to the next subprogram. The initial value is always part of the output for a scan, so we have to discard it at the end (t).

So, how does the helper function compute the result of a Deadfish command?

S&≠256!ë→a□?←0c     Takes a character (one of "ids") and an accumulator,
                     returns the new value for the accumulator
              c     Convert the character to its codepoint value
      !ë            and use it to index into this list of four functions:
        →            Increment
         a           Absolute value (dummy)
          □          Square
           ?←0       If nonzero then decrement else return 0
S&≠256              Return the result if ≠256, else 0

The trick here is that ord(c)%4 will return a different value for each c in "ids" (respectively 1,0,3). List indexing in Husk is modular so by indexing with this value into the list of functions we will get the function we need. a is there only to pad the list to 4 elements (because otherwise 's' and 'd' would have the same value modulo 3).

We check for -1 by only decreasing the accumulator if its value is not 0, and we check for 256 explicitly after any command.

\$\endgroup\$
3
\$\begingroup\$

Pyth, 59 bytes

FNz=T%CN4IqN"o"Z=tT)IqT1=hZ)IqT0=tZ)IqT3=*ZZ)I}hZ[0 257)=Z0

Try it online!

Bit out of practice. :)

\$\endgroup\$
3
\$\begingroup\$

AWK, 83 81 bytes

Thanks to Dominic van Essen for shaving off 2 bytes...

{for(;c=$++b%9;)printf c-3?(d=(x=c-6?c-1?d*d:--d:++d)<1?0:x==256?0:x)?f:f:+d"\n"}

This is pretty brute force, but it's ugly enough that I wanted to submit it. :) It's mostly abusing ternaries to save characters.

The input is code points separated by spaces as commandline arguments. The code converts them to modulo-9 to shorten the comparisons to the specific command values.

There's a minor trick on the printf line that might be worth highlighting.

printf c-3?..not-a-print-command..:d"\n"

prints the accumulator value when a o command is found.

The logic in the "truthy" part updates the accumulator, but always returns a value of f. Since that's a uninitialized variables, AWK picks a value based on the content where it's used. In this context it turns into a null string, so printf doesn't produce any output for non-o commands.

The code to update the accumulator is bundled into the print statement, so it's only called for a, d, i, and s commands. As result it doesn't have to check for o.

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I don't think you need to initialize d=0 if you output +d to specify a numeric 0 (rather than null string) for undefined value. Try it... \$\endgroup\$ Commented Jan 31, 2021 at 22:46
3
\$\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\$
3
\$\begingroup\$

Ohm v2, 30 bytes

ÝL}`7%5%›0s:_ΦD256â0>*
›
=
‹
²

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ This is a really clever use of wires! \$\endgroup\$ Commented Feb 17, 2021 at 15:47
3
\$\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\$
3
+100
\$\begingroup\$

Knight, 57 bytes

;=a 0W=cP I?c"o"Oa=a*=a I?c"d"-a 1I?c"i"+1a^a 2!|?256a>0a

Takes in each character on a separate input line.

Explanation

Here's the code with generous whitespace and comments added:

;=a 0       #set a to 0
W=cP        #  while the next input character `c` is not null:
 I?c"o"     #    if c is "o": 
  Oa        #      output a
  =a        #    else...
   *=a      #      set a to the following:
   I?c"d"   #      (if a is "d": 
    -a 1    #         a-1
    I?c"i"  #       else if a is "i":
     +1a    #         a+1
     ^a 2   #       else a^2)
   !|?256a>0a   #    multiply a by (not (a is 256) or (0>a)), which is 1 when a is within bounds and 0 otherwise

An earlier version where I tried to use some more clever tricks which ended up being longer (66 bytes):

;=a 0W =cP I?c"o"Oa=a*=aE S G"^2-1+1"/%Ac 23 3 2 1 0"a "!|?256a>0a
\$\endgroup\$
2
\$\begingroup\$

PHP, 136 bytes

<?php $w=0;foreach(str_split($argv[1])as$v){if($v=='o'){echo$w.' ';}else{$w=$v=='s'?$w**2:($v=='i'?++$w:--$w);}if($w==256||$w<0){$w=0;}}

Example explained:

$w=0;                                   #declare w var, is accumulator
foreach(str_split($argv[1])as$v){       # for each char of first CLI argument
if($v=='o'){                            #if output
echo$w.' ';                             #output w
}else{                                  #otherwise
$w=                                     #set w to
$v=='s'?                                #if input is s
$w**2                                   #squared
:($v=='i'?                              #otherwise if incremented
++$w:                                   #add one
--$w);}                                 #otherwise subtract one
if($w==256||$w<0){$w=0;}}               #if -1 or 256 set 0

PHP is annoying for this. Is run php deadfish.php <program>

Note: run on CLI so no online example.

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to the site, and nice first answer! Be sure to check out our Tips for golfing in PHP page for more ways you could golf your answer. \$\endgroup\$ Commented Jan 31, 2021 at 10:45
2
\$\begingroup\$

Red, 106 bytes

func[s][a: 0 parse s[any[(if a xor 256 < 1[a: 0])"i"(a: a + 1)|"d"(a: a - 1)|"s"(a: a * a)|"o"(print a)]]]

Try it online!

Pretty simple solution :

f: func[s][
    a: 0
    parse s[
       any[
           (if a xor 256 < 1[a: 0]) 
            "i"(a: a + 1)
           |"d"(a: a - 1)
           |"s"(a: a * a)
           |"o"(print a)
       ]
    ]
]
\$\endgroup\$
2
\$\begingroup\$

PowerShell, 68 bytes

switch -r($args){i{$a++}d{$a--}s{$a*=$a}o{+$a}.{$a*=$a-notin-1,256}}

Try it online!

\$\endgroup\$

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