Write an interactive Deadfish interpreter

30

5

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
>> 

marinus

Posted 2013-12-21T19:37:08.163

Reputation: 30 224

Are we allowed to take input with uppercase letters instead? – lirtosiast – 2015-07-04T20:06:09.357

I believe d is double, not decrement – SuperJedi224 – 2015-10-07T12:48:27.783

Can we assume all statements will end with o or c? – MayorMonty – 2016-07-31T17:46:49.327

Because of the prompting for input, I can't use GolfScript :-( – ProgramFOX – 2013-12-22T10:04:13.553

@ProgramFOX: You can use ruby input right? – marinus – 2013-12-23T06:02:52.240

According to the GolfScript tutorial, you can't prompt for input in GolfScript, all input comes from STDIN. – ProgramFOX – 2013-12-23T08:22:44.337

@ProgramFOX: I would have thought something like #{STDIN.gets} would work but indeed it doesn't. – marinus – 2013-12-23T08:33:06.787

Answers

6

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.

geocar

Posted 2013-12-21T19:37:08.163

Reputation: 214

8

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!

Dom Hastings

Posted 2013-12-21T19:37:08.163

Reputation: 16 415

1No longer the shortest answer. – geocar – 2016-07-31T11:51:53.863

1Your 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). – Konrad Borowski – 2013-12-22T11:46:26.003

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! – Dom Hastings – 2013-12-22T13:17:37.690

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! – Dom Hastings – 2013-12-22T13:58:40.300

OK, you're the shortest. – marinus – 2014-01-01T11:10:46.293

Using a -F flag and combining the first two conditions can get this down to 77 bytes of code: Try it online!

– Xcali – 2018-02-20T21:39:50.893

@Xcali As this needs to be interactive (and print out the >> before first input) I don't think I can use -n/-F. :( but I can definitely combine the first two checks, that great, thanks! – Dom Hastings – 2018-02-21T08:49:52.277

6

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

Ry-

Posted 2013-12-21T19:37:08.163

Reputation: 5 283

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. – shiona – 2013-12-22T16:19:15.423

@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? – Ry- – 2013-12-22T17:52:42.823

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. – shiona – 2013-12-22T18:03:37.283

@shiona: Oh! Good call, thank you! – Ry- – 2013-12-22T19:46:27.373

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. – shiona – 2013-12-22T20:04:02.047

You can save some bytes by using (>>), using pure and getting rid of the import: Try it online! (see my solution for why this works).

– ბიმო – 2018-02-15T20:23:20.807

6

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.

Danko Durbić

Posted 2013-12-21T19:37:08.163

Reputation: 10 241

Nice! Love the decrement by !!$x, shame I can't utilise that... – Dom Hastings – 2013-12-23T10:08:44.130

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!) – Dom Hastings – 2013-12-25T20:41:20.617

I've added some test output to the answer. – Danko Durbić – 2013-12-25T21:38:31.467

6

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]

kealist

Posted 2013-12-21T19:37:08.163

Reputation: 211

4

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
>>

Doorknob

Posted 2013-12-21T19:37:08.163

Reputation: 68 138

4

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
>>

tmartin

Posted 2013-12-21T19:37:08.163

Reputation: 3 917

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. – geocar – 2016-07-31T11:47:38.047

4

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.

Jérémy Ruelle

Posted 2013-12-21T19:37:08.163

Reputation: 41

1Welcome 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) – TuxCrafting – 2016-07-31T13:32:14.613

4

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();
}

FireFly

Posted 2013-12-21T19:37:08.163

Reputation: 7 107

3

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!

jazzpi

Posted 2013-12-21T19:37:08.163

Reputation: 846

1You can use lambda instead of def for a function that immediately returns. – Konrad Borowski – 2013-12-21T22:37:55.100

x in(-1,256) saves two characters. Alternatively, s=lambda x:"a=%d"%(x!=-1and x!=256and x) could save some. – Ry- – 2013-12-21T22:50:03.527

1You 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. – golfer9338 – 2013-12-23T00:41:25.740

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! – Darren Stone – 2013-12-24T04:54:15.877

3

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();}

Darren Stone

Posted 2013-12-21T19:37:08.163

Reputation: 5 072

3

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
>> 

Sven Hohenstein

Posted 2013-12-21T19:37:08.163

Reputation: 2 464

3

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. :)

Dave J

Posted 2013-12-21T19:37:08.163

Reputation: 209

I realize I'm VERY late to the party, but the lambda for m can be y*(-1!=y!=256) for -3 bytes – Reinstate Monica – 2019-06-07T12:30:15.180

just 5 years :) thanks for the input though. I am too lazy to fix the answer not but I'll keep it in mind – Dave J – 2019-06-25T07:05:51.643

3

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

stackspace

Posted 2013-12-21T19:37:08.163

Reputation: 31

3

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.

lirtosiast

Posted 2013-12-21T19:37:08.163

Reputation: 20 331

2

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#""

ბიმო

Posted 2013-12-21T19:37:08.163

Reputation: 15 345

2

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();}}

Konrad Borowski

Posted 2013-12-21T19:37:08.163

Reputation: 11 185

Wouldn't it be shorter to just remove the define q and just use printf? – Doorknob – 2013-12-22T04:30:17.137

@DoorknobofSnow Actually no. q is used 3 times, so define q saves ~2 chars. – Justin – 2013-12-22T06:34:06.153

2

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

luser droog

Posted 2013-12-21T19:37:08.163

Reputation: 4 535

2

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 _

Egor305

Posted 2013-12-21T19:37:08.163

Reputation: 23

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 – mniip – 2013-12-26T17:44:30.283

@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.

– Egor305 – 2013-12-26T21:59:31.697

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 – mniip – 2013-12-27T09:22:53.267

1

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.

Timtech

Posted 2013-12-21T19:37:08.163

Reputation: 12 038

2This one just plain does not work at all (Windows 7). I don't mean to be an asshole but did you test this? – marinus – 2013-12-23T08:48:52.130

@marinus It's been fixed. – Timtech – 2014-01-08T22:19:20.863

1

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();
}

user77406

Posted 2013-12-21T19:37:08.163

Reputation:

1

Keg, 68B

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

user85052

Posted 2013-12-21T19:37:08.163

Reputation:

1

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

Robert Sørlie

Posted 2013-12-21T19:37:08.163

Reputation: 1 036

1

><>, 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.

Aaron

Posted 2013-12-21T19:37:08.163

Reputation: 3 689

0

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.

Timtech

Posted 2013-12-21T19:37:08.163

Reputation: 12 038

1Still doesn't follow the rules, and uses uppercase letters rather than lowercase. – lirtosiast – 2015-07-04T00:59:00.690

1If you know about TI-BASIC, it only supports uppercase input. – Timtech – 2015-07-04T14:45:55.740

Which other solutions prompt one command at a time? – Ry- – 2013-12-22T19:47:10.360

The Perl and Haskell ones. – Timtech – 2013-12-22T23:18:06.767

1I 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. – Ry- – 2013-12-23T01:33:25.143

@minitech: For fun I did add a Perl one that doesn't print a prompt and accepts one char only per line at 77 chars. – Dom Hastings – 2013-12-23T08:16:51.867

1This doesn't follow the I/O rules. – marinus – 2013-12-23T08:57:10.630

0

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?

danmcardle

Posted 2013-12-21T19:37:08.163

Reputation: 695

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.

– ბიმო – 2018-02-15T20:24:56.907

0

C#, 311 bytes

using System;class p{static void Main(){int a=0;int s(int b)=>b==-1||b==256?0:b;while(true){Console.Write(">>");var c=Console.ReadLine();for(int i=0;i<c.Length;i++){switch(c[i]){case'i':case'x':a=s(a+1);break;case'd':a=s(a-1);break;case's':case'k':a=s(a*a);break;case'o':case'c':Console.WriteLine(a);break;}}}}}

would be 283 byte if usings and class declaration etc could be ommitted by just providing a function definition

Robin B

Posted 2013-12-21T19:37:08.163

Reputation: 101

0

05AB1E, 50 bytes

0[„>>,I"idsoxdkc"©Ãε®skн}"><n="sè"Džz1(‚såi0}"ý.V 

Try it online!

Explanation:

The basic idea is to translate it into 05AB1E code and eval it.

0[„>>,I"idsoxdkc"©Ãε®skн}"><n="sè"Džz1(‚såi0}"ý.V
0                                                    Set the accumulator to 0.
 [                                                   Do this forever.
  „>>,                                               Print ">>"
      I                                              Read input
       "idsoxdkc" Ã                                  Keep only "idsoxdkc" characters.
                 ©                                   Also put "idsoxdkc" in the register.
                   ε    }                            For each character in the filtered input:
                    ®skн                             Find it's index in "idsoxdkc"
                         "><n="sè                    Index into "><n="
                                 "Džz1(‚såi }"ý      After each command, check if accumulator = -1 or 256
                                           0         If it does, change it to 0
                                               .V    Evaluate as 05AB1E code.

Comrade SparklePony

Posted 2013-12-21T19:37:08.163

Reputation: 5 784

0

Tidy, 136 bytes

a:=0{h:a:=a+1 if h='i∨h='xa:=a-1 if h='da:=a*a if h='s∨h='kout(a)if h='o∨h='ca:=0 if a=-1∨a=256}→stoa(h)while h:=prompt(">> ")

Try it online! prompt is interactive, so it looks a bit weird online. See the "Example run" section below.

Ungolfed and commented

? initialize the accumulator
acc := 0

map(

    ? map this function...
    { char :
        acc := acc + 1      if char = 'i  or  char = 'x
        acc := acc - 1      if char = 'd
        acc := acc * acc    if char = 's  or  char = 'k
        out(acc)            if char = 'o  or  char = 'c
        acc := 0            if acc  = -1  or  acc  = 256
    },

    ? over each character...
    stoa(line)

? over each line
) while line := prompt(">> ")

Example run

C:\Users\conorpc\Programming\Tidy (master -> origin)
λ tidy test.tidy
>> xiskso
0
>> xiskisc
289
>> ddddo ddddo
285
281
>> ddddo ddddo
277
273
>> dddddddo
266
>> dddddddddo
257
>> do
0
>> do
0
>> io
1
>> 

Conor O'Brien

Posted 2013-12-21T19:37:08.163

Reputation: 36 228

0

Emojicode, 308 bytes

0➡️a>>❗️c❗️↪️dxdikscoc❗️➡️i↪️i◀4a⬅️➕i2✖2➖1↪️i◀6a⬅️✖️aa 10❗️❗️↪️a-1a2560➡️a

Try it online here.

Ungolfed:

    Main code block
    0 ➡️   a   Accumulator, initialised to 0
         Repeat forever:
         >> ❗️   Output prompt
         c    ❗️    For each character c in the next line of input:
            ↪️  dxdiksco c ❗️ ➡️ i    If the character is a valid command, get its index i in the string "dxdiksco"
                ↪️ i ◀ 4    If that index is less than 4, it is either the increment or the decrement command ...
                    a ⬅️ ➕ i  2 ✖ 2 ➖ 1   ... adjust accumulator accordingly
                
                 ↪️ i ◀ 6    Else, if it is smaller than 6, it is the square command ...
                    a ⬅️ ✖️ a   ... multiply the accumulator by itself
                     Else, it must be the print command ...
                      a 10 ❗️❗️   .. output the accumulator in base 10, followed by a line feed
                
                ↪️ a  - 1  a  256    If the accumulator is now either -1 or 256 ...
                    0 ➡️  a   ... reset it to 0
                
            
        
    

O.O.Balance

Posted 2013-12-21T19:37:08.163

Reputation: 1 499

0

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

Einacio

Posted 2013-12-21T19:37:08.163

Reputation: 436

0

><>, 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.

phase

Posted 2013-12-21T19:37:08.163

Reputation: 2 540

0

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

MayorMonty

Posted 2013-12-21T19:37:08.163

Reputation: 778