74
\$\begingroup\$

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.
\$\endgroup\$
11
  • 4
    \$\begingroup\$ I thought we were going to interpret Fish' lyrics :-( \$\endgroup\$ Commented Apr 9, 2015 at 8:47
  • 10
    \$\begingroup\$ @RemcoGerlich Not that Fish either \$\endgroup\$ Commented Apr 9, 2015 at 9:05
  • 4
    \$\begingroup\$ Finally a code-golf for RFC 3889 General Fish Transfer Format (implementing RFC3500: Standard Fish Transfer Format)! \$\endgroup\$
    – Sanchises
    Commented Apr 9, 2015 at 9:39
  • 12
    \$\begingroup\$ Bonus 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. \$\endgroup\$
    – mbomb007
    Commented Apr 9, 2015 at 18:26
  • 3
    \$\begingroup\$ I saw this and scrolled down, resigned to the fact that this would be @Calvin'sHobbies and nobody, nobody else. \$\endgroup\$ Commented Apr 10, 2015 at 15:12

22 Answers 22

31
\$\begingroup\$

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:

$$\begin{align*} M & = (Q, \Sigma, \iota, \sqcup, A, \delta) \\ Q & = \{q_{0},q_{1},q_{2},q_{3},q_{4},q_{5},q_{6},q_{7},q_{8},q_{9},q_{10},q_{11},q_{12},q_{13},q_{14},q_{15},q_{16},q_{17},q_{18},q_{19}\} \\ \Sigma & = \{< \: ; \: > \: ; \: , \: ; \: . \: ; \: X \: ; \: $\} \\ \iota & = q_0 \\ \sqcup & = $ \\ A & = \{q_0, q_5\} \end{align*}$$

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.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ Apparently I +1 for insanity. \$\endgroup\$
    – Kzqai
    Commented Apr 16, 2015 at 13:42
24
\$\begingroup\$

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.

\$\endgroup\$
2
  • 10
    \$\begingroup\$ What do you know, there are (at least) two right languages for this job! Someone (who is no me) should do the other one :-) \$\endgroup\$
    – xebtl
    Commented Apr 10, 2015 at 9:33
  • 2
    \$\begingroup\$ Same 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 \$\endgroup\$ Commented Apr 12, 2015 at 16:58
23
\$\begingroup\$

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

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

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
\$\endgroup\$
5
  • \$\begingroup\$ Is the online compiler too slow to run it on the example input in the question ? \$\endgroup\$
    – Optimizer
    Commented Apr 9, 2015 at 12:42
  • \$\begingroup\$ Yes, much too slow / too short a time out. ><>><>> takes 15 seconds on my machine. \$\endgroup\$
    – isaacg
    Commented Apr 9, 2015 at 12:49
  • 28
    \$\begingroup\$ O(9^n), holy inefficiency! \$\endgroup\$
    – mbomb007
    Commented Apr 9, 2015 at 17:56
  • 2
    \$\begingroup\$ @mbomb007 I don't see anything about efficiency in the rules :P +1! \$\endgroup\$
    – John Odom
    Commented Apr 9, 2015 at 18:50
  • 3
    \$\begingroup\$ @mbomb007: Probably still better than a C++ compiler. \$\endgroup\$ Commented Apr 12, 2015 at 16:44
13
\$\begingroup\$

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])
\$\endgroup\$
4
  • \$\begingroup\$ @Sp3000 Good catch, I think I know the problem. \$\endgroup\$
    – xnor
    Commented Apr 9, 2015 at 10:05
  • \$\begingroup\$ @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. \$\endgroup\$
    – xnor
    Commented Apr 9, 2015 at 10:12
  • \$\begingroup\$ Since you're in Python 3 already, you might as well (ab)use it :P *l,s=[],input() \$\endgroup\$
    – Sp3000
    Commented Apr 9, 2015 at 10:31
  • \$\begingroup\$ you forgot to decrease the byte count when you did ^that \$\endgroup\$ Commented Apr 9, 2015 at 13:16
13
\$\begingroup\$

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})/
\$\endgroup\$
3
  • \$\begingroup\$ You can knock off a few bytes if you factorise, e.g. ><(>|<<)> \$\endgroup\$
    – Sp3000
    Commented Apr 10, 2015 at 1:25
  • \$\begingroup\$ @Sp3000: Thanks! That does save a byte for each direction of fish. \$\endgroup\$ Commented Apr 10, 2015 at 11:02
  • \$\begingroup\$ It's actually shorter to use the same pattern, but without the code execution inside the match: Try it online! \$\endgroup\$
    – Xcali
    Commented Sep 25 at 19:02
6
\$\begingroup\$

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.

\$\endgroup\$
6
\$\begingroup\$

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)
\$\endgroup\$
1
  • 3
    \$\begingroup\$ I 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. \$\endgroup\$
    – mathmandan
    Commented Apr 9, 2015 at 13:28
4
\$\begingroup\$

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"";
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Oh, you got me. Didn't see it was a multiple definition. Removed comment to reduce noise. \$\endgroup\$
    – Kroltan
    Commented Apr 10, 2015 at 23:16
3
\$\begingroup\$

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)()""
\$\endgroup\$
1
  • 2
    \$\begingroup\$ This prints an error message if the input can't be split, as opposed to failing silently. \$\endgroup\$
    – Zgarb
    Commented Apr 10, 2015 at 7:37
3
\$\begingroup\$

Jelly, 35 bytes

“¦¿ÆבB;¬$ị⁾<>“,<..>,”ṭ
J¢ṗẎẎ⁼¥Ƈ⁸ḢK

Try it online!

This is brutally inefficient, clocking in at around (I believe) \$O(9^{n^2})\$, and times out on TIO for strings of length \$7\$ or more

Returns 0 if the input cannot be interpreted as fish

A much faster version is 38 bytes, timing out for length \$21\$ or more

How it works

Similar to isaacg's Pyth answer, we generate all possible fish strings, then look for the one(s) equal to the input

“¦¿ÆבB;¬$ị⁾<>“,<..>,”ṭ - Helper link. Returns a list of fish
“¦¿Æב                  - [5,11,13,17]
      B                 - Convert to binary; [[1,0,1],[1,0,1,1],[1,1,0,1],[1,0,0,0,1]]
        ¬               - Logical NOT of each bit; [[0,1,0],[0,1,0,0],[0,0,1,0],[0,1,1,1,0]]
       ; $              - Concatenate to the bits; [[1,0,1],[1,0,1,1],...,[0,0,1,0],[0,1,1,1,0]]
          ị⁾<>          - Index into "<>", replacing 1 with < and 0 with >
              “,<..>,”  - Yield the crab
                      ṭ - Append it to the fish

J¢ṗẎẎ⁼¥Ƈ⁸ḢK - Main link. Takes a fish F of length n on the left
J           - Yield [1, 2, ..., n]
 ¢          - Get the list of fish
  ṗ         - For each i in 1,2,...,n get the i'th Cartesian power of the fish
   Ẏ        - Concatenate into a list of lists
      ¥Ƈ    - Keep those lists for which the following is true:
    Ẏ       -   When concatenated into a flat list of characters,
     ⁼      -   the list equals
        ⁸   -   the input F
         Ḣ  - Take the first list of fish
          K - Join by spaces
    
\$\endgroup\$
3
\$\begingroup\$

Vyxal, 34 bytes

Lƛ»√ĿẆ;»ðøḂτ`,<.`+øṀ⌈↔vṄ;f≬ȧ?=c¤$∨

Try it Online!

I initially attempted to solve this with regex, but it's actually quite tricky, so this is a bruteforcer. Despite technically being \$O(9^n)\$ in the length of the input, thanks to Vyxal's laziness this will actually terminate within reasonable time for strings containing 5ish fish, although it will take ages for invalid strings. This could be 29 bytes with looser I/O (returning 0 in the fail case, returning a list of fish)

Lƛ                      ;          # Over every integer from 1 to the input length
                     ↔             # Get all combinations of that length of
  »√ĿẆ;»                           # Compressed integer
           τ                       # Converted to custom base
        ðøḂ                        # "< >", yielding "><> >><> ><>> ><<<> "
            `,<.`+                 # Append ",<." (half a crab)
                  øṀ               # Mirror
                    ⌈              # Split on spaces
                      vṄ           # And join each combination on spaces
                         f    c    # Out of all of those
                          ≬---     # Find one where
                           ȧ       # Removing whitespace
                            ?=     # Yields the input?
                               ¤$∨ # Return nothing otherwise
\$\endgroup\$
2
\$\begingroup\$

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.

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

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.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ The challenge explicitly asks for a full program that prints its output, as opposed to a function. \$\endgroup\$
    – Zgarb
    Commented Apr 9, 2015 at 15:11
1
\$\begingroup\$

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

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

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.

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

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 ''
}
\$\endgroup\$
1
\$\begingroup\$

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)

\$\endgroup\$
2
  • \$\begingroup\$ Fail with example ><>><>>. I think this can't solved so easily with Regexp, you need some lookahead or backtrak or whatsoever... \$\endgroup\$
    – edc65
    Commented Apr 10, 2015 at 8:53
  • \$\begingroup\$ @edc65 DAMN! For now, I don't have a solution. I'll try to fix later \$\endgroup\$ Commented Apr 10, 2015 at 9:30
1
\$\begingroup\$

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

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

<<>< ><<<> >><> ><> ><> <>< <>>>< >><> >><> >><> ><>> <<>< 
\$\endgroup\$
1
\$\begingroup\$

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()));
    }
}
\$\endgroup\$
1
\$\begingroup\$

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.

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

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(",<..>,><<<>,<..>,><>,<..>,<>>><,<..>,><>>,<..>,<<><,<..>,<><,<..>,>><>"));
}
\$\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.