32
\$\begingroup\$

Deadfish is a joke "programming language" with four commands. Because the Esolang page is a bit contradictory and the interpreters on that page don't all work exactly the same, you should implement the following variation:


Specification

  1. There is an accumulator which is at least 16 bits in size, more is allowed but less is not. Negative numbers do not need to be supported. The accumulator is 0 when the program starts.
  2. There are the following two sets of four commands, and your program must support both at the same time.
      Standard Deadfish    │   XKCD Variant   │    Meaning
      ─────────────────────┼──────────────────┼────────────────────────────────────
            i              │        x         │    Increment accumulator
            d              │        d         │    Decrement accumulator
            s              │        k         │    Square ( acc = acc * acc )
            o              │        c         │    Output accumulator, as a number
    
  3. If, after executing a command, the accumulator is either -1 or 256, the accumulator must be reset to zero. Note that this is not normal wrap-around. If, say, the accumulator is 20, and the s command is run, the accumulator should be 400 afterward. Similarly, if the accumulator is 257 and the d command is run, the accumulator should become 0.
  4. Any input that isn't one of these commands should be ignored.

Test programs

  • xiskso should output 0
  • xiskisc should output 289

I/O

Your program should display a prompt: >>. The prompt must be at the beginning of a new line. It should then read a line of user input, and run the given commands left-to-right. When outputing numbers, the numbers must be separated. I.e., 12 34 is OK, 12,34 is OK,

12
34 

is OK, but 1234 is not.

Your program should keep doing this in a loop, at least until EOF is reached.

Example session:

>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>> 
\$\endgroup\$
7
  • \$\begingroup\$ Because of the prompting for input, I can't use GolfScript :-( \$\endgroup\$
    – ProgramFOX
    Commented Dec 22, 2013 at 10:04
  • \$\begingroup\$ @ProgramFOX: You can use ruby input right? \$\endgroup\$
    – marinus
    Commented Dec 23, 2013 at 6:02
  • \$\begingroup\$ According to the GolfScript tutorial, you can't prompt for input in GolfScript, all input comes from STDIN. \$\endgroup\$
    – ProgramFOX
    Commented Dec 23, 2013 at 8:22
  • \$\begingroup\$ @ProgramFOX: I would have thought something like #{STDIN.gets} would work but indeed it doesn't. \$\endgroup\$
    – marinus
    Commented Dec 23, 2013 at 8:33
  • \$\begingroup\$ Are we allowed to take input with uppercase letters instead? \$\endgroup\$
    – lirtosiast
    Commented Jul 4, 2015 at 20:06

36 Answers 36

9
\$\begingroup\$

Perl 5, 90 bytes

do{print+(map{$?+=/i|x/-/d/;$?**=1+/s|k/;$?=~s/-1|^256$/0/;"$?
"x/o|c/}/./g),'>> '}while<>

Try it online!

Thanks to @xfix for his help on this previously! Saved 4 bytes thanks to @Xcali!

\$\endgroup\$
7
  • 1
    \$\begingroup\$ Your program prints 1 when accumulator overflows. Also, you can shorten your program by five characters, by changing $a to $? (which is initialized to 0, and won't change until you run some external program from Perl). \$\endgroup\$
    – null
    Commented Dec 22, 2013 at 11:46
  • \$\begingroup\$ Ahhhh, I was hunting for a variable I could use, perfect, thank you! As for overflowing, I didn't notice it as it only happens if you run issso as one command, not if you do each separately... I'll have a look at this later on and will certainly use $?. Thank you! \$\endgroup\$ Commented Dec 22, 2013 at 13:17
  • \$\begingroup\$ So I think I left an older version in the code section at the top with '' instead of "" so when used with perl -e '...' the map would end with the result of the s///. Thanks again! \$\endgroup\$ Commented Dec 22, 2013 at 13:58
  • \$\begingroup\$ OK, you're the shortest. \$\endgroup\$
    – marinus
    Commented Jan 1, 2014 at 11:10
  • 1
    \$\begingroup\$ No longer the shortest answer. \$\endgroup\$
    – geocar
    Commented Jul 31, 2016 at 11:51
7
\$\begingroup\$

K, 77 bytes

  {1">>";0{x*2=-1 256?x:y@x}/("xkcdiso"!7#(1+;{x*x};{-1@$x;x};-1+))@0:0;.z.s`}`
>>xiskso
0
>>xiskisc
289

Note this is K4. A K6 solution is slightly longer because the IO verbs are longer, even if everything else is better:

{""0:">>";0{x*^-1 256?x:y@x}/("xkcdiso"!7#(1+;{x*x};{""0:,$x;x};-1+))@0:"";o`}`
  • ""0: prints and returns its argument. Note in K4 we simply apply to 1.
  • 0 f/ args demonstrates reduce with an initial value, i.e. f[f[0;first arg];second arg]…
  • {x*2=-1 256?x… classifies x into the 0 (for -1), 1 (for 256) and 2 for all other values. 2= means we get 1 for unclassified values and 0 otherwise, multiplying by x is shorter than a conditional. In K6 we can do a little better because {x*^-1 256?x:y@x} relies on the fact that -1 256?x returns 0N (null) and ^ detects nulls.
  • The "parser" is the map "xkcdiso" instead of the suggested order because 7# will wrap around the four arguments i.e. 7#"abcd" returns "abcdabc" which keeps our table smaller
  • The map translates "x" and "i" to the projection 1+ which is equivalent to the function {1+x} but shorter.
  • The map translates "d" to the projection -1+ which is equivalent to the function {-1+x} but shorter.
  • The map translates "k" and "s" to the function {x*x}
  • The map translates "c" and "o" to the output function {-1@$x;x} which again in K6 is slightly longer: {""0:,$x;x} but both print its output followed by a newline, and then returns the argument.
  • .z.s is self-recursion. In K6 we can simply say o` which is shorter.
\$\endgroup\$
7
\$\begingroup\$

Powershell, 131 126 121 114 113

for($x=0){[char[]](read-host ">>")|%{switch -r($_){"i|x"{$x++}"d"{$x-=!!$x}"s|k"{$x*=$x}"o|c"{$x}}
$x*=$x-ne256}}
  • for($x=0){...} - set the accumulator to 0 and loop forever
  • read-host '>>' - get the user input with prompt >>
  • [char[]](...) - convert the user input to an array of characters
  • |%{...} - perform what's inside {} for each character
  • switch -r($_) - regex switch for each character
  • "i|x"{$x++} - match i or x - increase the accumulator
  • "d"{$x-=!!$x} - match d - decrease $x by !!$x, which will be 0 if $x is 0, and 1 otherwise. This makes sure the accumulator never reaches -1.
  • "s|k"{$x*=$x} - match s or k - square
  • "o|c"{$x} - match o or c - output the accumulator
  • $x*=$x-ne256 - multiply the accumulator by 0 if it is 256 or by 1 otherwise

Example output

>>: xiskso
0
>>: xiskisc
289
>>: ddddo ddddo
285
281
>>: ddddo ddddo
277
273
>>: dddddddo
266
>>: dddddddddo
257
>>: do
0
>>: do
0
>>: io
1
>>:

I guess the implementation of read-host is host specific, so this Powershell host (ConsoleHost) appends : to the specified prompt.

\$\endgroup\$
3
  • \$\begingroup\$ Nice! Love the decrement by !!$x, shame I can't utilise that... \$\endgroup\$ Commented Dec 23, 2013 at 10:08
  • \$\begingroup\$ Hey Danko, could you post some test output please? I don't think I can test power shell on non-windows... (please correct me if I'm wrong!) \$\endgroup\$ Commented Dec 25, 2013 at 20:41
  • \$\begingroup\$ I've added some test output to the answer. \$\endgroup\$ Commented Dec 25, 2013 at 21:38
7
\$\begingroup\$

Rebol 3, 178 169 161 159

f: does [if a = -1 or (a = 256)[a: 0]]d: [any[["i"|"x"](++ a f)|["d"](-- a f)|["s"|"k"](a: a * a f)|["o"|"c"](print a)| skip]]a: 0 forever [parse (ask ">>") d]

Prettier version:

f: does [if a = -1 or (a = 256) [a: 0]]
d: [
    any [
        ["i"|"x"] (++ a f) |
        ["d"] (-- a f) |
        ["s"|"k"] (a: a * a f) |
        ["o"|"c"] (print a) |
        skip
    ]
]
a: 0 
forever [parse (ask ">>") d]
\$\endgroup\$
6
\$\begingroup\$

Haskell, 202

r=pure;-1%c=0%c;256%c=0%c;s%'o'=s<$print s;s%'c'=s%'o';s%'i'=r$s+1;s%'x'=s%'i'
s%'d'=r$s-1;s%'s'=r$s^2;s%'k'=s%'s';s%_=r s;n s(c:[])=s%c;n s(c:f)=s%c>>=(`n`f)
main=p 0;p s=putStr">> ">>getLine>>=n s>>=p
\$\endgroup\$
6
  • \$\begingroup\$ You could probably save a few characters by changing e and v into operators. I also tried rewriting v and g so that the parameter x stays in IO, and print etc. get lifted. I didn't manage to get it working, but I think that might be a good place to go for someone who knows their haskell. \$\endgroup\$
    – shiona
    Commented Dec 22, 2013 at 16:19
  • \$\begingroup\$ @shiona: Yeah, the thing about keeping things in IO is that they either print too often (that’s why I used r n instead of x) or not enough because the value is never asked for…. So how would I change e and v into operators? \$\endgroup\$
    – Ry-
    Commented Dec 22, 2013 at 17:52
  • \$\begingroup\$ I had the same problems with printing. What comes to operators you can do (using e as example) 'i'%x=x+1;'d'%x=x-1... And just call it in v do n<-x;r$w$o%n. The reason operators save space is that they don't require spaces around them. \$\endgroup\$
    – shiona
    Commented Dec 22, 2013 at 18:03
  • \$\begingroup\$ @shiona: Oh! Good call, thank you! \$\endgroup\$
    – Ry-
    Commented Dec 22, 2013 at 19:46
  • \$\begingroup\$ No problem. I first thought about making an answer of my own but since I couldn't get my big ideas working I thought it would be just rude post exactly the same code with just different notation for the same functions. \$\endgroup\$
    – shiona
    Commented Dec 22, 2013 at 20:04
5
\$\begingroup\$

Python 3, 141

I know I am to late, but I wanted to take the opportunity to post a shorter Python-version (and my first CodeGolf-attempt). :)

v=0
m=lambda y:(0,y)[-1!=y!=256]
i=x='+1'
d='-1'
s=k='*v'
c=o=');print(v'
while 1:
 for n in input('>>'):exec('v=m(v'+locals().get(n,'')+')')

The print-statement was kinda tricky for this. If the prompt has to end with a whitespace, add one char to the count. :)

Explanation

v is the accumulator.

m checks whether the given value is -1 or 256. If so, 0 will be returned, the value otherwise.

In the following lines the operations are assigned to the corresponding variables (as some have the same meaning (like i and x) this is shorter than instantiating a new dictionary). Those are then used in the exec below.

while 1: is the main-loop

Now the fun begins. Like @jazzpi's solution, it iterates over each char of the input. locals() is the dictionary of all current (visible) variables. With .get(n,'') the corresponding key will be put into the exec-string (an empty string, if the key (= other input) was not found). This then will be, when executed, concatenated with v and passed towards m. The return value will be stored in v again.

Short example:

Be n = 'i' (n = input-char), we get '+1' out of the locals-block as i is the variable with value '+1'.
The string for the exec than looks like this: 'v=m(v+1)'.
Maybe now it is easier to see, that, when executing, it will call m with the value of v+1 and store it's output in v again.

Repeat this until you are bored. :)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I realize I'm VERY late to the party, but the lambda for m can be y*(-1!=y!=256) for -3 bytes \$\endgroup\$
    – squid
    Commented Jun 7, 2019 at 12:30
  • \$\begingroup\$ just 5 years :) thanks for the input though. I am too lazy to fix the answer not but I'll keep it in mind \$\endgroup\$
    – Dave J
    Commented Jun 25, 2019 at 7:05
4
\$\begingroup\$

Ruby, 140 138

a=0
loop{$><<'>> '
eval gets.gsub(/./){|c|({i:i='a+=1',x:i,d:'a-=1',s:s='a**=2',k:s,o:o='p a',c:o}[:"#{c}"]||'')+';a=a==-1||a==256?0:a;'}}

Sample session (same as yours):

c:\a\ruby>deadfish
>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>>
\$\endgroup\$
4
\$\begingroup\$

K, 121

i:0;while[1;1">> ";{i{(r;0)(-1~r)|256~r:y x}/d{x@&x in y}[x;!d:"ixdskoc"!,/(2#(1+);-1+;2#{x*x};2#{-1@$i::x;})]}'" "\:0:0]

.

C:\q>q deadfish.k -q
>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>>
\$\endgroup\$
1
  • \$\begingroup\$ My version is shorter. I compressed the map, relied on ? to classify for "wrapping" values, used recursion instead of while, and a functional interpreter instead of amend. \$\endgroup\$
    – geocar
    Commented Jul 31, 2016 at 11:47
4
\$\begingroup\$

Ada

Here's an Ada implementation for the few who're interested by this language. It took me quite some time in order to use some of Ada's best practices (like the use of Indefinite_Holders instead of access) and also to fully comprehend how's Deadfish must work.

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Indefinite_Holders;
with Ada.Integer_Text_IO;

procedure Deadfish is
   package String_Holder is new Ada.Containers.Indefinite_Holders(String);
   use String_Holder;

   value_output : Natural := 0;
   str_input : String_Holder.Holder := To_Holder("");
begin
   Prompt :
   loop
      Put(">> ");
      String_Holder.Replace_Element(str_input, Get_Line);
      for rg in str_input.Element'Range loop
         case str_input.Element(rg) is
            when 'i' | 'x' => 
               case value_output is
                  when 255 => value_output := 0;
                  when others => value_output := Natural'Succ(value_output);
               end case;

            when 'd'       =>                   
               case value_output is
                  when 257 => value_output := 0;
                  when 0 => null;
                  when others => value_output := Natural'Pred(value_output);
               end case;
            when 's' | 'k' => 
               case value_output is
                  when 16 => value_output := 0;
                  when others =>value_output := value_output * value_output;
               end case;
            when 'o' | 'c' => Ada.Integer_Text_IO.Put(value_output, Width => 0); Put_Line("");
            when others => null;
         end case;
      end loop;
   end loop Prompt;
end Deadfish;

And the output :

>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>>

If some people experimented in Ada could give me some optimisation hints, I would be thankful.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to PPCG! The goal of code-golf is to create the shortest possible code, and you should include the size of you program in the header (1396 bytes here) \$\endgroup\$ Commented Jul 31, 2016 at 13:32
4
\$\begingroup\$

C, 159 chars

A; main(c) {
  printf(">> ");
  while (c = getchar(), ~c)
    A = c - 'i' & c - 'x'?
        c - 'd'?
        c - 's' & c - 'k'?
        c - 'o' & c - 'c'?
        c - '\n'?
        A :
        printf(">> "), A :
        printf("%d\n", A), A :
        A * A :
        A - 1 :
        A + 1,
    A *= ~A && A - 256;
}

I tried another approach based on setting up a look-up table for instruction decoding, but unfortunately that ended up longer (169). I included it since someone might come up with a clever tweak to cut down the size. (Must be run without any arguments)

#define X !--c?A

A,M[256];
main(c) {
  for(; !M['x']; c++) M["@osid\nckx"[c]]-=c%5+1;
  for (printf(">> "); c = ~M[getchar()]; A *= ~A && A - 256)
  A= X,printf("%d\n", A),A:X*A:X+1:X-1:A;
  main();
}
\$\endgroup\$
1
3
\$\begingroup\$

C, 163

#define i(u,v);if(c==u+89|c==v+89)
a;main(c){printf(">>");while(c=getchar()-10){i(6,21)a++i(1,1)a--i(8,16)a*=a;i(0,12)printf("%d\n",a);a=a==-1|a==256?0:a;}main();}
\$\endgroup\$
3
\$\begingroup\$

Python 3, 181 175 171 162

a=0
s=lambda x:"a=%d"%(x!=-1and x!=256and x)
while 1:
 for i in input(">>"):u,b,o=s(a+1),s(a*a),"print(a)";exec(dict(i=u,x=u,d=s(a-1),s=b,k=b,o=o,c=o).get(i,""))

This outputs a newline after the >>, but the OP didn't say that wasn't allowed. Not anymore!

Thanks to GlitchMr, minitech and golfer9338!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can use lambda instead of def for a function that immediately returns. \$\endgroup\$
    – null
    Commented Dec 21, 2013 at 22:37
  • \$\begingroup\$ x in(-1,256) saves two characters. Alternatively, s=lambda x:"a=%d"%(x!=-1and x!=256and x) could save some. \$\endgroup\$
    – Ry-
    Commented Dec 21, 2013 at 22:50
  • 1
    \$\begingroup\$ You could remove print(">>") and use for i in input(">>") instead; input() allows specifying a prompt. Then, there will be no newline after >>, and you save characters. \$\endgroup\$
    – golfer9338
    Commented Dec 23, 2013 at 0:41
  • \$\begingroup\$ Your score should be, I think, one char shorter right now. Please doublecheck, but I get a count of 161 instead of the posted 162: lines of 3+40+8+107, plus 3 newlines. Truth be told, I'm jealous, because either way, you're a few chars shorter than my C answer. Cheers! \$\endgroup\$ Commented Dec 24, 2013 at 4:54
3
\$\begingroup\$

R, 161, 148, 138

a=0;repeat{x=readline(">> ");for(i in utf8ToInt(x)-99){a=a^((i==8|i==16)+1)+(i==6|i==21)-(i==1&a);a=a*(a!=256);if(i==0|i==12)cat(a,"\n")}}

Ungolfed version:

a = 0
repeat{
  x = readline(">> ")
  for(i in utf8ToInt(x) - 99) {
    a = a ^ ((i == 8 | i == 16) + 1) + (i == 6 | i == 21) - (i == 1 & a)
    a = a * (a != 256)
    if(i == 0 | i == 12) cat (a, "\n")
  }
}

Example session (in interactive mode):

>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>> 
\$\endgroup\$
3
\$\begingroup\$

Python 2, 139

a=0
while 1:
 for c in raw_input(">> "):
  if c in'ix':a+=1
  if c=='d':a-=1
  if c in'sk':a*=a
  if c in'oc':print a
  if a in(-1,256):a=0

This is neat, but also pretty straightforward. Here's a longer, cooler version:

def i(a):
 while 1:
  c=yield
  if c in'ix':a+=1
  if c=='d':a-=1
  if c in'sk':a*=a
  if c in'oc':print a
  if a in(-1,256):a=0
 j=i(0);next(j)
while 1: 
 for c in raw_input(">> "):j.send(c)

Weighing in at 190 characters, it's perhaps not the most competitively-lengthed answer here. On the other hand, coroutines are pretty rad and I'm always looking for an excuse to use (and share) them

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

TI-BASIC, 104 107 102 100 98

For TI-83+/84+ series calculators.

Name this prgmD; it eventually overflows the stack by calling itself. Replace the recursion with a While 1, at the cost of two bytes, to fix this.

Input ">>",Str1
For(I,1,length(Str1
int(.5inString("?ixskd?oc",sub(Str1,I,1
If Ans=4
Disp Y
imag(i^Ans)+Y^int(e^(Ans=2     //decrements when Ans=3; increments when Ans=1
min(0,Ans(Ans≠256→Y
End
prgmD

Y is 0 by default, so either run this with a freshly memory-cleared calculator or store 0 to Y manually before running this.

Too bad that the lowercase letters (in the string literals) are two bytes each; otherwise this would be shorter than Dom Hastings' answer.

EDIT: Fixed a divide-by-zero (0^0) error at the cost of three bytes.

107 -> 102: Used imaginary exponentiation trick to save four bytes (including 1 from parentheses and -1 from lengthening the lookup string) and used Y instead of X, which takes one less byte to initialize.

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

Postscript 272

/cmd<</i{1 add}/x 1 index/d{1 sub}/s{dup mul}/k 1 index/o{dup =}/c 1 index>>def
0{(>> )print flush{/f(%lineedit)(r)file def}stopped{exit}if{f
1 string readstring not{exit}if cmd exch 2 copy known{get exec}{pop pop}ifelse
dup -1 eq 1 index 256 eq or{pop 0}if}loop pop}loop

Ungolfed:

/cmd <<  % define commands
/i { 1 add }
/x 1 index
/d { 1 sub }
/s { dup mul }
/k 1 index
/o { dup = }
/c 1 index
>> def
0        % accumulator on stack
{
    (>> )print flush   % print prompt
    { /f (%lineedit) (r) file def } stopped {exit} if  % read input line or quit
    {
        f 1 string readstring not {exit} if   % read 1-char string from line
        cmd exch 2 copy known { get exec }{ pop pop } ifelse   % execute command or don't
        dup -1 eq 1 index 256 eq or { pop 0 } if   % adjust accumulator if needed
    } loop
    pop
}loop
\$\endgroup\$
2
\$\begingroup\$

C (224 212 characters)

This is probably a bad language choice, but oh well. It's not that language like C can do better than some dynamic programming language. On Clang, you will need to specify a value for return (this is not necessary for gcc).

#define s(x,y)case x:y;break;
main(){int c=10,a=0;for(;;){switch(c){s(-1,return)s('i':case'x',++a)s('d',--a)s('s':case'k',a*=a)s('c':case'o',printf("%d\n",a))s(10,printf(">> "))}a!=-1&a!=256||(a=0);c=getchar();}}
\$\endgroup\$
3
  • \$\begingroup\$ Wouldn't it be shorter to just remove the define q and just use printf? \$\endgroup\$
    – Doorknob
    Commented Dec 22, 2013 at 4:30
  • \$\begingroup\$ @DoorknobofSnow Actually no. q is used 3 times, so define q saves ~2 chars. \$\endgroup\$
    – Justin
    Commented Dec 22, 2013 at 6:34
  • \$\begingroup\$ 156 bytes \$\endgroup\$
    – ceilingcat
    Commented Jun 30, 2020 at 23:15
2
\$\begingroup\$

Haskell, 186 178 bytes

This needs to be run with runhaskell (or inside ghci) since they both set the BufferMode to NoBuffering by default which safes quite a lot of bytes:

infix 4#
-1#x=0#x
256#x=0#x
r#x:y=case x of 'i'->r+1#y;'x'->r+1#y;'d'->r-1#y;'s'->r^2#y;'k'->r^2#y;'o'->print r>>r#y;'c'->r#'o':y;_->r#y
r#_=putStr">> ">>getLine>>=(r#)
main=0#""

Try it online!

Explanation

This defines a new operator state # source (the fixity declaration allows us to drop parentheses when using it in conjunction with other operators (+),(-),(^),(:) and (>>)):

  • the first two lines "fix" the states -1 and 256
  • it then matches the first character and acts upon it
  • once it runs out of characters (r#_), it reads new ones and starts over again keeping the old state

To start the process we initialize the state with 0 and read a new source line, ie. begin with an empty source:

main=0#""
\$\endgroup\$
2
\$\begingroup\$

Python 3, 130 119 bytes

a=0
while 1:
 for c in input(">> "):
  a+=(c in'ix')-(c=='d')+(a*a-a)*(c in'sk')
  if c in'oc':print(a)
  a*=-1!=a!=256

Try it online!

This is just a conversion of stackspace's response to Python 3, with an improvement to the wrap-around code. We gain 1 byte from losing the print statement, but save 4 bytes from switching to input(), and remove another 6 from the new wrap-around code.

Edit: Saved another 11 bytes by moving all the math operations onto one line. Moving the square operation doesn't actually save any bytes, but it does look cooler.

\$\endgroup\$
3
  • \$\begingroup\$ You can save a few bytes by doing a-=c=='d' and a+=c in'ix' instead of the first 2 if statements \$\endgroup\$ Commented Aug 29, 2021 at 14:39
  • \$\begingroup\$ Welcome to the site! Piggy backing off of the suggestion from @Dudecoinheringaahing you can then combine the two lines into one as a+=(c in'ix')-(c=='d') \$\endgroup\$
    – Wheat Wizard
    Commented Aug 29, 2021 at 15:18
  • \$\begingroup\$ That is evil. Thank you both. \$\endgroup\$ Commented Aug 29, 2021 at 20:17
1
\$\begingroup\$

Lua, 230 228

a=0repeat io.write(">> ")x=io.read()for i=1,#x do c=x:sub(i,i)if c=="i"or c=="x"then a=a+1 elseif c=="d"then a=a-1 elseif c=="s"or c=="k"then a=a*a elseif c=="o"or c=="c"then print(a)end if a==256or a==-1then a=0 end end until _

Not the worst, not the best.

NOTE: as reported by @mniip 256or may not work in your interpreter. More info in comments.

(more or less) Readable version:

a=0
repeat
  io.write(">> ")
  x=io.read()
  for i=1,#x do
    c=x:sub(i,i)
    if c=="i"or c=="x"then
      a=a+1
    elseif c=="d"then
      a=a-1
    elseif c=="s"or c=="k"then
      a=a*a
    elseif c=="o"or c=="c"then
      print(a)
    end
    if a==256or a==-1then
      a=0
    end
  end  
until _

Output:

>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>>

Edit: thanks to @mniip for 2 char optimization: until nil -> until _

\$\endgroup\$
3
  • \$\begingroup\$ repeat until x (x is nil as not been defined) is 2 chars shorter, and while 1 do end is exact same length, other than that what lua version is that? 256or is invalid syntax in my interpreter \$\endgroup\$
    – mniip
    Commented Dec 26, 2013 at 17:44
  • \$\begingroup\$ @mniip Thanks for hint about repeat until x. I'm using latest windows binary from here. As you can see a=a+1 elseif have space. That's because e is hexadecimal digit, while o in 256or is not, so my interpreter takes or as another statement/block/howYouCallIt. \$\endgroup\$
    – Egor305
    Commented Dec 26, 2013 at 21:59
  • \$\begingroup\$ yeah pretty much besides 256or, also 0repeat and 1then; I am using official lua from lua.org, your code doesn't compile in either 5.1, 5.2, or 5.3 \$\endgroup\$
    – mniip
    Commented Dec 27, 2013 at 9:22
1
\$\begingroup\$

Windows Batch, 204 256

@echo off
set a=0
:a
set /p i=^>^> 
if %i%==i set /a a=%a%+1
if %i%==x set /a a=%a%+1
if %i%==d set /a a=%a%-1
if %i%==s set /a a=%a%*%a%
if %i%==k set /a a=%a%*%a%
if %i%==o echo %a%
if %i%==c echo %a%
if %a%==256 set a=0
if %a%==-1 set a=0
set i=n
goto a

Successfully ignores other commands. Really got bloated without having or to work with...

Edit:

Fixed:

  • No more Echoing all commands
  • Made it actually DO math with /a
  • Reset on -1
  • Reset input after every cycle

This cost 52 characters.

Didn't fixed:

  • Squaring 0 writes "0*0" in a.
  • Inputting space (or inputing nothing, when you just opened it) crashes script.
  • You NEED to input one char at a time.
\$\endgroup\$
2
  • 2
    \$\begingroup\$ This one just plain does not work at all (Windows 7). I don't mean to be an asshole but did you test this? \$\endgroup\$
    – marinus
    Commented Dec 23, 2013 at 8:48
  • \$\begingroup\$ @marinus It's been fixed. \$\endgroup\$
    – Timtech
    Commented Jan 8, 2014 at 22:19
1
\$\begingroup\$

Windows Command Script - 154

Abusin unknown features to the max.

@echo off
set i=1
set x=1
set d=-1
set/as=[*[-[
set/ak=[*[-[
set.=0
set/p.=^>^> 
set/a[=[+%.%
e%.:o=c%h%.:c=o% %[% 2>nul
set[=%[:-1=%
if;%[%==256 set[=
%0
\$\endgroup\$
1
\$\begingroup\$

><>, 258 bytes

I've done another ><> answer since I couldn't test phase's and it used pre-stacked commands rather than emulating a shell anyway.

0v
"<vooo">> 
!~>i:0)?v~ >
 ^?=a:  /  ^!?="c"v?="o":v?="s":v?="k":v?="d":v?="x":v?="i":
   voan:<        ~<  v*:~<      <  v-1~<  v+1~<      <
   <                 <             <      <vv?=-10:v?=*:+1f:
  v                                        <>      >~0

It can certainly be golfed down, but I'm not sure I'll have the needed insanitybravery !

I tested it with the official interpreter running under python 3.5 under cygwin under windows 7 and could reproduce the test run :

$ python fish.py deadfish.fish
>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>> (pressed ctrl-Z)Stopped

In case you can't run it on your machine (input seems to be tricky) or you just want to try it without any other software, you can use the following version on the online interpreter.

0v
 <vooo">> "<
  >i:0)?v~
      o:/  ^!?="c"v?="o":v?="s":v?="k":v?="d":v?="x":v?="i":
 ^oanoa:<        ~<  v*:~<      <  v-1~<  v+1~<      <
   <                 <             <      <vv?=-10:v?=*:+1f:
  v                                        <>      >~0

It obviously disregards \n and EOF since you can't input them in the online interpreter, but will behave as if enter had been pressed after each output command.

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

C (gcc), 139 bytes

Compile with -Dk="_nZZiaeY" (included in byte count). -2 bytes if prompt >>\n is allowed.

x;f(c){for(printf(">>");c=getchar()-10;x+=c--?c--?c--?c||printf("%i\n",x),0:x*x-x:-1:1,x*=~x&&x^256)c=strchr(k,c)-k>>1;f();}

Try it online!

Degolf

/** Preprocessor **/
-Dk="_nZZiaeY" // This is a lookup string; it corresponds to "ixddskoc",
               // with 10 deducted from each character. Upon compilation, 
               // all occurences of the string literal are replaced with a 
               // pointer to its location in memory.

/** Source **/
x;f(c){ // x: 32-bit accumulator, c: local variable for read character
    for(printf(">>"); // Start for-loop and print prompt.
            c=getchar()-10; // Read a character from STDIN.
                            // Loop breaks if it is '\n'.

            // The below happens at the end of each iteration.
            x+=c--?c--?c--? 
               // Find the correct operation by testing c and post-
               // decrementing with multiple ternary-ifs. If c is 0, 
               // operation was found, add the else-value to the 
               // accumulator x.
               //     If the character is invalid, the value of c is
               // very large, and will not reach 0 with 3 decrements.

               c||printf("%i\n",x),0 
               // If c-3 is 0, print accumulator, else do nothing.
               // Returns 0 regardless of what happens. (No change to x)
               :x*x-x 
               // Square. Results in x=x+x*x-x, and is shorter than (x*=x)
               :-1:1, 
               // Decrement, Increment.
               x*=~x&&x^256 
               // Because -1==0xffffffff, ~x==0 when x==-1. Likewise,
               // x^256==0 only when x==256. The logical-AND coerces the result
               // to boolean 1 (no match) or 0 (match). Multiplication resets
               // the accumulator as appropriate.
           )
        // This is the actual body of the for-loop
        c=strchr(k,c)-k>>1; 
           // Finds the index of the read character in the lookup string,
           // then "divides" it by two.
           // Because strchr() returns NULL (0) when character is not found,
           // deducting k from it results in a very negative number.
           // The right-shift results in division by 2 for positive numbers, 
           // while the negative numbers become very large positive numbers
           // (c >= 0x70000000) because of the 2's complement representation.
    // Finally, recurse until forceful termination.
    f();
}
\$\endgroup\$
1
\$\begingroup\$

Keg, 68B

0{'::"ÿ1+=$0<+['_0"] \>\>\
,,,,?:o=[':."]:i=['1+"]:d=['1-"]:s=[':*"
\$\endgroup\$
0
\$\begingroup\$

Haskell, 230

import System.IO
i""n=[]
i(a:b)n 
 |a=='o'||a=='c'=[n]++i b n
 |True=i b$v a n
v a n=w(case a of 'i'->n+1;'x'->n+1;'d'->n-1;'s'->n^2;'k'->n^2)
w(-1)=0
w 256=0
w n=n
main=do;putStr ">> ";hFlush stdout;s <- getLine;print$i s 0;main

If only I could get rid of that pesky hFlush stdout call! Without it, the prompt is not displayed until an o operation is performed. Any advice?

\$\endgroup\$
1
  • \$\begingroup\$ You can get rid of the hFlush by using runhaskell instead of compiling (see my answer), but as for this solution it's not valid and errors out. \$\endgroup\$ Commented Feb 15, 2018 at 20:24
0
\$\begingroup\$

PHP+HTML 345

<form><?php $i=0;$o='';if(isset($_GET[i])){$i=$_GET[a];foreach(@str_split($_GET[i]) as $j=>$v){$v==i||$v==x?$i++:($v==d?$i--:($v==k||$v==s?$i*=$i:($v==o||$v==c?$o.=$i."\n":'')));($i==256||$i==-1)&&$i=0;}$_GET[p].='>> '.$_GET[i]."\n".$o;echo"<textarea locked name=p>$_GET[p]</textarea><input type=hidden name=a value=$i><br>";}?>>> <input name=i>

output is a little sketchy (history/session is shown on a textarea, and with error reporting enabled a lot warnings are printed) but everything works

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

><>, 239

v
\r0&
v                  <
\&::&01-=$f1+:*=+?v
v             &0~&<
\:"i"=?v
       >~&1+&      ^
\:"d"=?v
       >~&1-&      ^
\:"s"=?v
       >~&:*&      ^
\:"o"=?v
       >~&:o&      ^
\:"h"=?v
       >~;        (^)
>~                 ^

The initial stack is the input. You can try it online here.

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

Golf-Basic 84, 88 characters

:0_A:0_O:1_I:2_D:3_S:O_C:I_X:S_Kl`1i`N@A=256:0_A@N=0d`A@N=1:A+1_A@N=2:A-1_A@N=3:A^2_Ag`1

Prompts one command at a time, as in at least 3 other solutions. Here is a test run for xiskisc:

?X
?I
?S
?K
?I
?S
?C
             289

Also, xiskso outputs 0, as it should.

\$\endgroup\$
7
  • \$\begingroup\$ Which other solutions prompt one command at a time? \$\endgroup\$
    – Ry-
    Commented Dec 22, 2013 at 19:47
  • 1
    \$\begingroup\$ I wrote the Haskell one, and no, it doesn’t. Nor does the Perl one, so I’m really not sure what you’re talking about. \$\endgroup\$
    – Ry-
    Commented Dec 23, 2013 at 1:33
  • 1
    \$\begingroup\$ This doesn't follow the I/O rules. \$\endgroup\$
    – marinus
    Commented Dec 23, 2013 at 8:57
  • 1
    \$\begingroup\$ Still doesn't follow the rules, and uses uppercase letters rather than lowercase. \$\endgroup\$
    – lirtosiast
    Commented Jul 4, 2015 at 0:59
  • 1
    \$\begingroup\$ If you know about TI-BASIC, it only supports uppercase input. \$\endgroup\$
    – Timtech
    Commented Jul 4, 2015 at 14:45
0
\$\begingroup\$

JavaScript (Node.js), 204 Bytes

process.openStdin(f=a=>process.stdout.write((i=0,""+a).split` `.map(x=>([...x.slice(0,-1)].map(d=>({i:x=e=>i++,d:e=>i--,s:k=e=>i*=i,o:c=e=>e,x,k,c})[d](i=-1||i==256?i=0:0)),i))+"\n>> "),f``).on("data",f)

This can probably be golfed. Node.js again proves it's strange disguised verbosity once again. Code explained:

process.openStdin( // This function has to be called to take input, but doesn't have arguments
  f=a=> // Define a function f. This is the deadfish interpreter. It takes an argument `a` which is a Buffer
  process.stdout.write( // Same as console.log, but doesn't output trailing newline
    (i = 0, "" + a) // Take advantage of comma operator to (A) define the accumulator i, and casts a (which is a Buffer) to a String
      .split` ` // Split the string a at spaces, making it an array
      .map(     // Map through each element of the array
        x=>     // Map function, takes argument x, the value in the array (string)
          ([...x.slice(0,-1)] // Remove the last character (newline) and than use the spread operator to divide the string into an array of it's chars
            .map(d=> // Map function, you know how this works
              ({ // Here I define the various deadfish commands
                i: x = e => i++,
                d: e => i--,
                s: k = e => i*=i,
                o: c = e => e,
                // Take advantage of ES6 object notation. Equivilent to {"x": x, "k": k, "c", c}
                x,
                k,
                c
              })
              [d] // Get the command to execute. If this is passed something which isn't valid, a giant error will appear
              (
                i==-1 || i==256 ? i = 0 : 0 // Take advantage of the fact that none of the command functions take arguments to handle the strange "overflow"
              )
            ),
          i)
      ) +
  "\n>> "), // Display the prompt again, as well as a newline
  f`` // Initalize the prompt by passing an empty script
)
.on("data",f) // Bind the f function to newline on STDIN
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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