Interpreting Fish (no, not that Fish)

69

9

Consider these five ASCII art sea creatures:

  1. Standard fish: ><> or <><
  2. Speedy fish: >><> or <><<
  3. Sturdy fish: ><>> or <<><
  4. Stretchy fish: ><<<> or <>>><
  5. Crab: ,<..>,

Write a program that accepts an arbitrary string of the characters <>,.. If there is a way to interpret the entire string as a series of non-overlapping sea creatures, then the string should be reprinted with single spaces inserted between creatures. If this interpretation is impossible, nothing should be output (the program silently ends).

For example, the string <><><> can be interpreted as two standard fish back-to-back. The corresponding output would be <>< ><>.

As another example, the string ><>><>> contains "instances" of...
(brackets only added as indicators)

  • a couple standard fish: [><>][><>]>
  • a speedy fish: ><[>><>]>
  • a sturdy fish in a couple ways: [><>>]<>> and ><>[><>>]

however, only the pairing of a standard fish and a sturdy fish [><>][><>>] spans the entire length of the string with no fish sharing characters (no overlaps). Thus the output corresponding to ><>><>> is ><> ><>>.

If there are multiple ways the string could be interpreted, you may print any one of them. (And only print one of them.) For example, <><<<>< can be interpreted as a standard fish and a sturdy fish: [<><][<<><], or as a speedy fish and a standard fish: [<><<][<><]. So either <>< <<>< or <><< <>< would be valid output.


The crabs are just for fun. Since they don't start or end with < or >, they are much easier to identify (at least visually). For example, the string

,<..>,><<<>,<..>,><>,<..>,<>>><,<..>,><>>,<..>,<<><,<..>,<><,<..>,>><>

would obviously produce the output

,<..>, ><<<> ,<..>, ><> ,<..>, <>>>< ,<..>, ><>> ,<..>, <<>< ,<..>, <>< ,<..>, >><>

Here are some examples of strings (one per line) that produce no output:

<><>
,<..>,<..>,
>>><>
><<<<>
,
><><>
,<><>,
<<<><><<<>>><>><>><><><<>>><>><>>><>>><>><>><<><

The last string here can be parsed if you remove the leading <:

<<>< ><<<> >><> ><> ><> <>< <>>>< >><> >><> >><> ><>> <<><

(There may be other possible outputs.)

Details

  • The input string will only contain the characters <>,..
  • The input string will be at least one character long.
  • Take input in any common way (command line, stdin) and output to stdout.
  • The shortest code in bytes wins. (Handy byte counter.) Tiebreaker is earlier post.

Calvin's Hobbies

Posted 2015-04-09T05:44:29.303

Reputation: 84 000

Nice codegolf with parallels to compression (greedy/lazy substring matching) – schnaader – 2015-04-09T08:42:36.013

4I thought we were going to interpret Fish' lyrics :-( – RemcoGerlich – 2015-04-09T08:47:13.760

9@RemcoGerlich Not that Fish either – Calvin's Hobbies – 2015-04-09T09:05:43.060

4Finally a code-golf for RFC 3889 General Fish Transfer Format (implementing RFC3500: Standard Fish Transfer Format)! – Sanchises – 2015-04-09T09:39:06.407

11Bonus points if you do it using BrainF***! And the longer it takes your program to realize its own code isn't fish-compliant, the better. – mbomb007 – 2015-04-09T18:26:27.603

3I saw this and scrolled down, resigned to the fact that this would be @Calvin'sHobbies and nobody, nobody else. – Soham Chowdhury – 2015-04-10T15:12:14.270

1((><>)|(<><)|(>><>)|(<><<)|(><>>)|(<<><)|(><<<>)|(<>>><)|(,<..>,))+ – Kevin – 2015-04-11T08:09:28.543

@Kevin: Exactly what I was thinking when I saw this question :D – Mark K Cowan – 2015-04-12T16:42:12.670

what about ><><> from this string you can create two independent fish, how this should be handled? – user902383 – 2015-04-13T12:24:13.463

@user902383 There are two fish in there but they overlap, so there is no output. – Calvin's Hobbies – 2015-04-13T20:38:22.487

Answers

21

Pyth, 64 48 50 bytes

#jdhfqzsTsm^+msXtjCk2U2"<>""
\r.1"",<..>,"dlzB

Test case.


Version that doesn't take forever (O(9n/3)) here, in 52 bytes.


This is the brute force approach, generate all sequences and check whether any sum to the input. Fish diagrams compressed as characters, whose binary representations are the > and <. The whole thing is wrapped in a try-catch block so that no output occurs when no results are found.

This is an O(9n) solution.

Some characters are stripped above, because control characters are used. They are reproduced faithfully at the link above.

xxd output:

0000000: 236a 6468 6671 7a73 5473 6d5e 2b6d 7358  #jdhfqzsTsm^+msX
0000010: 746a 436b 3255 3222 3c3e 2222 0a5c 7212  tjCk2U2"<>"".\r.
0000020: 141b 1d2e 3122 222c 3c2e 2e3e 2c22 646c  ....1"",<..>,"dl
0000030: 7a42                                     zB

isaacg

Posted 2015-04-09T05:44:29.303

Reputation: 39 268

Is the online compiler too slow to run it on the example input in the question ? – Optimizer – 2015-04-09T12:42:28.797

Yes, much too slow / too short a time out. ><>><>> takes 15 seconds on my machine. – isaacg – 2015-04-09T12:49:23.400

28O(9^n), holy inefficiency! – mbomb007 – 2015-04-09T17:56:36.327

2@mbomb007 I don't see anything about efficiency in the rules :P +1! – John Odom – 2015-04-09T18:50:32.897

3@mbomb007: Probably still better than a C++ compiler. – Mark K Cowan – 2015-04-12T16:44:01.987

27

Non-deterministic Turing Machine, 20 states, 52 transitions (882 bytes maybe)

How do you convert this to bytes? I've written the files (absolutely not golfed) to execute this machine with Alex Vinokur's Simulator of a Turing Machine1. wc -c outputs the following (excluding the description file and the input files):

 12 alphabet
 49 meta
740 rules
 81 states
882 total

Anyways, I was preparing for my Computer Science A-Levels, so I thought this would be a good exercise (I don't know what I was thinking). So here's the definition:

Definition

States

Alphabet

Initial state

Blank character

Accepting states

Transition function

(the transition function)

Excuse the bad image, but I couldn't be bothered with redrawing this thing on a computer. If you actually want to decipher the transition rules, I recommend you read through the rules file I linked above.


I've used Xs instead of spaces because spaces are hard to visualize here and the simulator doesn't accept spaces in the alphabet.

The concept is fairly simple - q1 to q4 are used to catch right-facing fishes, q11 to q14 are used to catch left-facing fishes, q15 to q19 for crabs and the q5 to q10 blob is simply for inserting a space and moving all following characters one to the right.

If the string is interpretable, it accepts the string and the tape contains the string with spaces inserted. Otherwise it rejects the string (I guess this counts as no output - emptying the tape would be pretty easy but would require lots of transition rules and I don't think it would make the transition function prettier to look at).


1 Note: It's difficult to compile. I had to edit the src/tape.cpp file and replace LONG_MAX with 1<<30 and then go to the demo directory, edit the Makefile to replace EXE_BASENAME with turing.exe and execute make. Then go to the directory with the files I've written and execute /path/to/turing/download/src/turing.exe meta.

jazzpi

Posted 2015-04-09T05:44:29.303

Reputation: 846

3Apparently I +1 for insanity. – Kzqai – 2015-04-16T13:42:42.967

22

fish (yes, that fish), 437 bytes

This strikes me as one of those programming tasks where exactly one language is right.

#!/usr/bin/fish

set the_fishes "><>" "<><" ">><>" "<><<" "><>>" "<<><" "><<<>" "<>>><" ",<..>,"
set my_fishes

function startswith
        set -l c (echo -n $argv[2]|wc -c)
        echo $argv[1]|cut -c(math $c+1)-
        test $argv[2] = (echo $argv[1]|cut -c-$c)
end

function pickafish
        set -l fix 1
            while true
                if test $fix -gt (count $the_fishes); return 1; end

                if not set rest (startswith $argv[1] $the_fishes[$fix])
                            set fix (math $fix+1)
                        continue
                end    
                set my_fishes $my_fishes $the_fishes[$fix]
                    if test -z $rest
                        echo $my_fishes
                            exit
                    end
                    if not pickafish $rest
                    set my_fishes $my_fishes[(seq (math (count $my_fishes) - 1))]
                    set fix (math $fix+1)
                        continue
                end
        end
end

pickafish $argv[1]

The following version is still the longest answer to the challenge,

set t "><>" "<><" ">><>" "<><<" "><>>" "<<><" "><<<>" "<>>><" ",<..>,";set m;function p;set -l i 1;while true;test $i -gt 9; and return 1;if not set r (begin;set c (echo $t[$i]|wc -c);echo $argv[1]|cut -c$c-;test $t[$i] = (echo $argv[1]|cut -c-(math $c-1));end);set i (math $i+1);continue;end;set m $m $t[$i];if test -z $r;echo $m;exit;end;if not p $r;set m $m[(seq (math (count $m)-1))];set i (math $i+1);continue;end;end;end;p $argv[1]

but since this was done mostly for the pun (you'll excuse, I hope), better golfing is left as an exercise to the reader.

xebtl

Posted 2015-04-09T05:44:29.303

Reputation: 941

9

What do you know, there are (at least) two right languages for this job! Someone (who is no me) should do the other one :-)

– xebtl – 2015-04-10T09:33:33.853

2Same program in 383 chars of BASH with a BASE64 blob included:

printf 'H4sIADSjKlUCA4VPQW6DMBC89xUj5AOocSSOlV1/BHGgjgMrBUPN0kRRHl/jmEg99WBLszM7M7s4BqMw2hQotNHxNy+QkDYJZU7rTJqED/p4NIdCLdFmVOfVW6bJY04DeQGhVteBLg4cVqfYLQxBkD3jQ6HzJwTHa/BRRmf4ibEtBpRfriefXCxKZ4cJghtB7eNqIW2lnqMu9D9N3T7sGtOssDInJCk+982/MlmOHQ+I6rqKRv5UpRxCntN7XSk7eSYfK0f+eR3EmI23qilH3iFCrjIqdyNO8nzJvJH7alMu7jsnlHZafWw5VluD9r/0/c2vQ95+AYBxAwS2AQAA'|base64 --decode|gzip -d>a;fish a – Mark K Cowan – 2015-04-12T16:58:24.870

20

><>, 602 bytes

0&>i:0)?vr>:5%4-?v}:5%?;}:5%1-?;}:5%1-?;}:5%2-?;}:5%4-?;}&~0& v
  \     /        >:5%2-?v}:5%2-?v}:5%?v}:5%2-?v}              v
 &:?v;>*} ^      v      <       >:5% ?v}:5%?v} :5% ?v}:5%2-?v}v
v&-1< ^48<                                  >: 5%2-?v}:5%2-  ?v&1+&0}}v
>    :?v~^       >:5%?v}:5%?v}:5%2-  ?v}:5%  ?v}              v
^~v?%8:<                    >:5%2-?v}: 5%2-?v} :5%2- ?v}:5%?v}v
^{<        >0>=?;:v                         >: 5%    ?v}:5%  ?v&1+&0}}v
           ^lo~<  <   >            >  >       >     > >     >  02.
          \}*48^?=i:                                          <       <

A solution in Fish, probably very golfable but it's my first ><> program. It takes its input from the input stack and runs on the online ><> interpreter.

How it works :

A loop reads all the input and stacks it, reverse it and put a -1 on the bottom wich will mark that parsing is complete (all characters stay on the stack until the string is deemed parsable).
The parsing uses the fact all characters are different modulo 5, and all patterns are deterministic except <><< and ><>>. Parsed characters are put on the bottom of the stack.
When a pattern is complete, if -1 is on top, all characters are printed, otherwise a space is added and the program loops.
If <><< or ><>> are encountered, the register is incremented (0 at the start), and a 0 is placed on the stack before the last character (so that <>< or ><> stays after rollback). If an error appears afterwards during parsing, the register is decreased, all characters after the 0 are put back on top (except spaces thanks to a %8=0 test).
If an error is detected while the register is 0, or inside the crab, the program just ends immediately.

David D

Posted 2015-04-09T05:44:29.303

Reputation: 201

13

Python 3, 156

*l,s=[],input()
for _ in s:l+=[y+[x]for x in"><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,".split()for y in l]
for y in l:
 if"".join(y)==s:print(*y);break

The strategy is to generate lists of fish and compare their concatenation to the input string.

This takes impossibly long. If you actually want to see an output, replace for _ in s with for _ in [0]*3, where 3 is the upper bound for the number of fish. It works to use s because s contains at most one fish per char.

Thanks to Sp3000 for bugfixes and a char save on input.

Old 165:

f=lambda s:[[x]+y for x in"><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,".split()for y in f(s[len(x):])if s[:len(x)]==x]if s else[[]]
y=f(input())
if y:print(*y[0])

xnor

Posted 2015-04-09T05:44:29.303

Reputation: 115 687

@Sp3000 Good catch, I think I know the problem. – xnor – 2015-04-09T10:05:25.227

@Sp3000 I think it should work now. This was a case of the ternary a and b or c giving a wrong value when b might be Falsey. I reverted to if/else for 2 chars, but there might be a way to make the ternary work. – xnor – 2015-04-09T10:12:51.863

Since you're in Python 3 already, you might as well (ab)use it :P *l,s=[],input() – Sp3000 – 2015-04-09T10:31:37.750

you forgot to decrease the byte count when you did ^that – undergroundmonorail – 2015-04-09T13:16:06.277

12

Perl, 81 + 1 bytes

/^((>><>|><(|>|<<)>|<><<|<(|<|>>)><|,<\.\.>,)(?{local@a=(@a,$2)}))*$(?{say"@a"})/

Try this code online.

This code expects the input in the $_ variable; run this with Perl's -n switch (counted as +1 byte) to apply it to each input line, e.g. like this:

perl -nE '/^((>><>|><(|>|<<)>|<><<|<(|<|>>)><|,<\.\.>,)(?{local@a=(@a,$2)}))*$(?{say"@a"})/'

This code uses Perl's regexp engine (and specifically its embedded code execution feature) to perform an efficient backtracking search. The individual fishes found are collected in the @a array, which is stringified and printed if the match is successful.

This code also uses the Perl 5.10+ say feature, and so must be run with the -E or -M5.010 switch (or use 5.010;) to enable such modern features. By tradition, such switches used solely to enable a particular version of the language are not included in the byte count.

Alternatively, here's a 87-byte version that requires no special command-line switches at all. It reads one line from stdin, and prints the result (if any) to stdout, without any trailing linefeed:

<>=~/^((>><>|><(|>|<<)>|<><<|<(|<|>>)><|,<\.\.>,)(?{local@a=(@a,$2)}))*$(?{print"@a"})/

Ps. If printing an extra space at the beginning of the output was allowed, I could trivially save two more bytes with:

/^((>><>|><(|>|<<)>|<><<|<(|<|>>)><|,<\.\.>,)(?{local$a="$a $2"}))*$(?{say$a})/

Ilmari Karonen

Posted 2015-04-09T05:44:29.303

Reputation: 19 513

You can knock off a few bytes if you factorise, e.g. ><(>|<<)> – Sp3000 – 2015-04-10T01:25:11.293

@Sp3000: Thanks! That does save a byte for each direction of fish. – Ilmari Karonen – 2015-04-10T11:02:44.337

6

Python 2, 234 bytes

I tried a Python regex solution first, but there seems to be no way to extract the groups after a match on multiple patterns. The following is a recursive search which seems to do well on the test cases.

a='><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,'.split()
def d(t,p=0):
 if p<len(t):
  for e in a:
   z=p+len(e)
   if e==t[p:z]:
    if z==len(t):return[e]
    c=d(t,z)
    if c:return[e]+c
c=d(raw_input())
if c:
 print' '.join(c)

An example test:

$ echo ",<..>,><<<>,<..>,><>,<..>,<>>><,<..>,><>>,<..>,<<><,<..>,<><,<..>,>><>" | python soln.py 
,<..>, ><<<> ,<..>, ><> ,<..>, <>>>< ,<..>, ><>> ,<..>, <<>< ,<..>, <>< ,<..>, >><>

And the ungolfed version:

fishtypes = '><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,'.split()

def getfish(t, p=0):
    if p < len(t):
        for afish in fishtypes:
            z = p+len(afish)
            if afish == t[p:z]:
                if z == len(t) :
                    return [afish]
                fishlist = getfish(t, z)
                if fishlist :
                    return [afish]+fishlist

fishlist = getfish(raw_input())
if fishlist:
    print ' '.join(fishlist)

Logic Knight

Posted 2015-04-09T05:44:29.303

Reputation: 6 622

3I think your very last if can be on a single line (like you did elsewhere). Also, instead of if p<len(t) I think you can do if t[p:] to save a few bytes. – mathmandan – 2015-04-09T13:28:29.073

6

Python 3, 196 186 bytes

F="><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,".split()
def g(s):
 if s in F:return[s]
 for f in F:
  i=len(f)
  if f==s[:i]and g(s[i:]):return[f]+g(s[i:])
R=g(input())
if R:print(*R)

Simple recursion. g either returns a list of parsed fish, or None if the input string is unparseable.

Sp3000

Posted 2015-04-09T05:44:29.303

Reputation: 58 729

4

C# - 319 bytes

This solution is shamefully simple, hardly anything to Golf. It's a complete program, takes input as a line from STDIN, and outputs the result to STDOUT.

using C=System.Console;class P{static void Main(){C.Write(S(C.ReadLine()));}static string S(string c){int i=c.LastIndexOf(' ')+1;foreach(var o in"<>< ><> <<>< ><>> >><> <><< ><<<> <>>>< ,<..>,".Split()){string k=c+"\n",m=c.Substring(i);if(m==o||m.StartsWith(o)&&(k=S(c.Insert(i+o.Length," ")))!="")return k;}return"";}}

It simply attempts to match each fish to the first position after a space (or at the start of the string), and matches each type of fish with it. If the fish fits, then it recursively calls the solver after inserting a space after the fish, or simply returns it's input (with a \n for output reasons) if the unmatched string is literally the fish (i.e. we've found a solution).

I haven't made much of an attempt to give the fish string the usual kolmogorov treatment, because it isn't all that long, and I can't find a cheap way to reverse a string in C# (I don't think LINQ will pay), so there may be some opportunity there, but I somewhat doubt it.

using C=System.Console;

class P
{
    static void Main()
    {    
        C.Write(S(C.ReadLine())); // read, solve, write (no \n)
    }

    static string S(string c)
    {
        int i=c.LastIndexOf(' ')+1; // find start of un-matched string

        // match each fish
        foreach(var o in"<>< ><> <<>< ><>> >><> <><< ><<<> <>>>< ,<..>,".Split())
        {
            string k=c+"\n", // set up k for return if we have finished
            m=c.Substring(i); // cut off stuff before space
            if(m==o|| // perfect match, return straight away
               m.StartsWith(o)&& // fish matches the start
               (k=S(c.Insert(i+o.Length," "))) // insert a space after the fish, solve, assign to k
               !="") // check the solution isn't empty
                return k;
        }

        // no fish match
        return"";
    }
}

VisualMelon

Posted 2015-04-09T05:44:29.303

Reputation: 3 810

Oh, you got me. Didn't see it was a multiple definition. Removed comment to reduce noise. – Kroltan – 2015-04-10T23:16:17.540

3

Haskell(Parsec) - 262

import Text.Parsec
c=words"><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,"
p c d=choice[eof>>return[],lookAhead(choice$map(try.string)d)>>=(\s->try(string s>>p c c>>=(\ss->return$s:ss))<|>p c(filter(/=s)c))]
main=interact$either show unwords.runParser(p c c)()""

swish

Posted 2015-04-09T05:44:29.303

Reputation: 7 484

2This prints an error message if the input can't be split, as opposed to failing silently. – Zgarb – 2015-04-10T07:37:20.873

2

import sys

def unfish(msg,dict,start):
    if(len(msg[start:])<3):
        return "";
    for i in range(3,6):
        if (msg[start:start+i] in dict):
            if(start+i==len(msg)):
                return msg[start:start+i];
            else:
                ret = unfish(msg,dict,start+i);
                if ret != "":
                    return msg[start:start+i]+" "+ret;
    return ""

dict = {'><>':1,'<><':1,'>><>':1,'<><<':1,'><>>':1,'<<><':1,'><<<>':1,'<>>><':1,',<..>,':1};

print unfish(sys.argv[1],dict,0);

im a bit of a python noob so ignore the weirdness :P

franklynd

Posted 2015-04-09T05:44:29.303

Reputation: 121

3

Welcome to PPCG. This is a code-golf challenge, meaning you should try to write the code with as few characters as possible. For a start you could use single letter variables (e.g. m instead of msg, s instead of start, ...) and use only 1 space per increment. And please post add the character-count of your program (you can count them here).

– Jakube – 2015-04-09T20:30:10.147

Thanks @Jakube , I didn't know that it was a golf challenge as well. Thanks for the tips. – franklynd – 2015-04-09T21:05:03.787

2

Ruby, 177 bytes

Not the shortest but the first one in ruby:

def r(e,p,m)t='';p.each{|n|t=e.join;return r(e<<n,p,m)if m=~/^#{t+n}/};(m==t)?e:[];end
puts r([],%w(><<<> <>>>< ><>> <<>< >><> <><< ><> <>< ,<..>,),gets.strip).join(' ')

The attempt here is to recursively extend a regexp and match it against the input.
If a longer match is found r() will recurse, if not it will check if the last match consumes the whole input string and only then output it with added spaces.

Shirkrin

Posted 2015-04-09T05:44:29.303

Reputation: 121

1

CJam, 111 96 91 (or 62 bytes)

An iterative greedy approach to keep figuring out what all fish combinations are possible as you iterate. Really not golfed right now.

q_aa\,{{" È÷®µãÑø"255b5b" ><,."f=S/\f{)_3$#{;;;}{2$,>:P@a\a++}?PR+!{S:R*W<o}*}~}%}*];

The code contains some unprintable characters, so use the link below for reference.

Update Encoded the string

Will add explanation once done golfing

Try it online here


62 bytes

Super slow version. This basically creates all the combinations and checks which are equal to the input.

L"¬ééãLù:9$"255b6b5," ><,."erS/aq:Q,*{m*}*{sQ=}=`"[]\""-

This also contains unprintable characters, so rely on the below link.

Try it online here

Optimizer

Posted 2015-04-09T05:44:29.303

Reputation: 25 836

1

Haskell, 148 146 bytes

main=mapM_ putStr.take 1.filter(all(`elem`words"><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,").words).map concat.mapM(\a->[[a],a:" "])=<<getLine

Testing:

$ echo "><>><>>>" | runhaskell fishes.hs

$ echo "><>><>>" | runhaskell fishes.hs

<> ><>>

Explanation

Based on my earlier answer to a similar question. The algorithm runs in exponential time.

This reads from right to left.

=<<getLine              -- Read a line from STDIN.
mapM(\a->[[a],a:" "])   -- Replace each letter 'a' by "a" or "a " in
                        -- all possible ways, collect results to a list.
map concat              -- Concatenate those lists-of-strings into strings.
filter(all(...).words)  -- Keep those whose words are correct fish.
take 1                  -- Discard all but the first one.
mapM_ putStr            -- Print each string in that 1- or 0-element list.
main=                   -- That is the main function.

This will not print a string that ends with a space, even though such strings are generated too, because its no-space counterpart is generated first.

Zgarb

Posted 2015-04-09T05:44:29.303

Reputation: 39 083

1

JavaScript (ES6), 164

Recursive, depth first scan.
As a program with I/O via popup:

alert((k=(s,r)=>'><>0<><0>><>0<><<0><>>0<<><0><<<>0<>>><0,<..>,'.split(0)
.some(w=>s==w?r=w:s.slice(0,l=w.length)==w&&(t=k(s.slice(l)))?r=w+' '+t:0)?r:'')
(prompt()))

As a testable function:

k=(s,r)=>'><>0<><0>><>0<><<0><>>0<<><0><<<>0<>>><0,<..>,'.split(0)
.some(w=>s==w?r=w:s.slice(0,l=w.length)==w&&(t=k(s.slice(l)))?r=w+' '+t:0)?r:''

Test suite (run in Firefox/FireBug console)

t=['<><><>', '><>><>>', '<><<<><',',<..>,><<<>,<..>,><>,<..>,<>>><,<..>,><>>,<..>,<<><,<..>,<><,<..>,>><>',
'<><>',',<..>,<..>,','>>><>','><<<<>',',','><><>',',<><>,',
'<<<><><<<>>><>><>><><><<>>><>><>>><>>><>><>><<><','<<><><<<>>><>><>><><><<>>><>><>>><>>><>><>><<><']

t.forEach(t=>console.log(t + ': ' +k(t)))

Output

<><><>: <>< ><>
><>><>>: ><> ><>>
<><<<><: <>< <<><
,<..>,><<<>,<..>,><>,<..>,<>>><,<..>,><>>,<..>,<<><,<..>,<><,<..>,>><>: ,<..>, ><<<> ,<..>, ><> ,<..>, <>>>< ,<..>, ><>> ,<..>, <<>< ,<..>, <>< ,<..>, >><>
<><>: 
,<..>,<..>,: 
>>><>: 
><<<<>: 
,: 
><><>: 
,<><>,: 
<<<><><<<>>><>><>><><><<>>><>><>>><>>><>><>><<><: 
<<><><<<>>><>><>><><><<>>><>><>>><>>><>><>><<><: <<>< ><<<> >><> ><> ><> <>< <>>>< >><> >><> >><> ><>> <<><

Ungolfed just the k function

function k(s)
{
  var f='><>0<><0>><>0<><<0><>>0<<><0><<<>0<>>><0,<..>,'.split(0) 
  var i, w, l, t

  for (w of f)
  {
    if (s == w)
    {
      return w
    } 
    l = w.length
    if (s.slice(0,l) == w && (t = k(s.slice(l))))
    {
      return w + ' ' + t
    }
  }
  return ''
}

edc65

Posted 2015-04-09T05:44:29.303

Reputation: 31 086

0

Python 3, 166 164 bytes

def z(s,p=''):[z(s[len(f):],p+' '+s[:len(f)])for f in'<>< <><< <<>< <>>>< ><> >><> ><>> ><<<> ,<..>,'.split(' ')if s.startswith(f)]if s else print(p[1:])
z(input())

Recursive solution. Late to the party, but I thought I'd post it anyway since it beats Sp3000's by 20 22 bytes without having to brute-force the answer.

Alexander Revo

Posted 2015-04-09T05:44:29.303

Reputation: 270

0

Haskell, 148 142

p[]=[[]]
p s=[i:j|i<-words"><> >><> ><>> ><<<> <>< <><< <<>< <>>>< ,<..>,",i==map fst(zip s i),j<-p$drop(length i)s]
    g s=unwords$head$p s++p[]

this uses list comprehensions to iterate over the fish, pick the ones who match the start and continue recursively.

proud haskeller

Posted 2015-04-09T05:44:29.303

Reputation: 5 866

3The challenge explicitly asks for a full program that prints its output, as opposed to a function. – Zgarb – 2015-04-09T15:11:38.890

0

Javascript (122 135 bytes)

Not the most golfed here, could be stripped down a little.

This one is regex based, and a tad hard to figure out what is going on.

alert(prompt(R=RegExp,r='(<<?><|><>>?|,<\.\.>,|>><>|><<<>|<><<|<>>><)').match(R('^'+r+'+$'))[0].split(R(r+'(?=[>,]|$)','g')).join(' '))

This one is a one-liner.

Basically, I check the syntax and then I split the string based on the chars and join it together.
It throws an exception when you give it an invalid input.

If it can't throw exceptions (126 139 bytes):

(i=prompt(R=RegExp,r='(<<?><|><>>?|,<\.\.>,|>><>|><<<>|<><<|<>>><)')).match(R('^'+r+'+$'))&&alert(i.split(R(r+'(?=[>,]|$)','g')).join(' '))

Both are one-liners.
Both work the same way.


Thank you @edc65 for detecting the edge case that wasn't working well.


You can test it here (output will be written to the document).

It is based on the version that throws exceptions when you introduce invalid code.

var alert=console.log=function(s){document.write(s)+'<br>';};
try{
alert(prompt(R=RegExp,r='(<<?><|><>>?|,<\.\.>,|>><>|><<<>|<><<|<>>><)').match(R('^'+r+'+\x24'))[0].split(R(r+'(?=[>,]|\x24)','g')).join(' '));
}catch(e){console.log(e);}

(Currently, there's a bug on stack snippets, I've posted in on meta It was already asked yesterday. For it to work, I've replaced $ with \x24, which has the same output. You can read about the bug here: http://meta.codegolf.stackexchange.com/questions/5043/stack-snippets-messing-with-js)

Ismael Miguel

Posted 2015-04-09T05:44:29.303

Reputation: 6 797

Fail with example ><>><>>. I think this can't solved so easily with Regexp, you need some lookahead or backtrak or whatsoever... – edc65 – 2015-04-10T08:53:17.873

@edc65 DAMN! For now, I don't have a solution. I'll try to fix later – Ismael Miguel – 2015-04-10T09:30:51.140

0

Scala, 299 Bytes

type S=String
type L[T]=List[T]
def c(s:S):L[L[S]]={val f=List("><>","<><",">><>","<><<","><>>","<<><","><<<>","<>>><",",<..>,").filter(s.startsWith);if(f.isEmpty)List(List(s)) else f.flatMap(i => c(s.drop(i.size)).map(i::_))}
def p(s:S)=println(c(s).find(_.last.isEmpty).fold("")(_.mkString(" ")))

Test Cases

val tests = Seq("><>", "<><", ">><>", "<><<", ">><>", "<><<", "><<<>", "<>>><", ",<..>,", "><>><>", "><><><", ",<..>,<><", "<<<><><<<>>><>><>><><><<>>><>><>>><>>><>><>><<><", "<<><><<<>>><>><>><><><<>>><>><>>><>>><>><>><<><")
tests.foreach(p)

Output

><> 
<>< 
>><> 
<><< 
>><> 
<><< 
><<<> 
<>>>< 
,<..>, 
><> ><> 
><> <>< 
,<..>, <>< 

<<>< ><<<> >><> ><> ><> <>< <>>>< >><> >><> >><> ><>> <<>< 

Dave Swartz

Posted 2015-04-09T05:44:29.303

Reputation: 185

0

Java, 288 bytes

public class F{public static void main(String[]q){d("",q[0]);}static System y;static void d(String a,String b){if(b.isEmpty()){y.out.println(a);y.exit(0);}for (String s : "><> <>< >><> <><< ><>> <<>< ><<<> <>>>< ,<..>,".split(" "))if(b.startsWith(s))d(a+" "+s,b.substring(s.length()));}}

Formatted:

public class F {
    public static void main(String[] q) {
        d("", q[0]);
    }

    static System y;

    static void d(String a, String b) {
        if (b.isEmpty()) {
            y.out.println(a);
            y.exit(0);
        }
        for (String s : "><> <>< >><> <><< ><>> <<>< ><<<> <>>>< ,<..>,".split(" "))
            if (b.startsWith(s)) d(a + " " + s, b.substring(s.length()));
    }
}

Landei

Posted 2015-04-09T05:44:29.303

Reputation: 109

0

I wasn't going for size, but here is an easy to understand way of doing this in Dart.

const List<String> fish = const [
  "><>",
  "<><",
  ">><>",
  "<><<",
  "><>>",
  "<<><",
  "><<<>",
  "<>>><",
  ",<..>,"
];

String fishy(String input) {
  var chars = input.split("");
  if (chars.isEmpty || !chars.every((it) => [">", "<", ",", "."].contains(it))) {
    throw new Exception("Invalid Input");
  }

  var result = [];
  var i = 0;
  var buff = "";
  while (i < chars.length) {
    buff += chars[i];

    if (fish.contains(buff)) {
      result.add(buff);
      buff = "";
    } else if (chars.length == 6) {
      return "";
    }

    i++;
  }

  return result.join(" ");
}

void main() {
  print(fishy(",<..>,><<<>,<..>,><>,<..>,<>>><,<..>,><>>,<..>,<<><,<..>,<><,<..>,>><>"));
}

kaendfinger

Posted 2015-04-09T05:44:29.303

Reputation: 1