21
\$\begingroup\$

Given two positive integers X and Y, output any combination of the following three ASCII-art animals such that the output contains exactly X commas (,) and Y periods (.), if it is possible.

  1. Koala: 1 comma, 2 periods

    <.,.>
    
  2. Crab: 2 commas, 2 periods

    ,<..>,
    
  3. Commapillar: 3 or more commas, 1 period

    <,,,.>
    

    or <,,,,.> or <,,,,,.> or <,,,,,,.> or <,,,,,,,.> etc.

If no combination of these animals can produce exactly X commas and Y periods, output a single commaleon who will camouflage the failure:

~<.,,>~~

The output animals can be in any amounts and any order. They may be in a string, space or newline separated, or else in a list where each animal is one element.

For example, for X = 7, Y = 5, these would all be valid outputs (separated by empty lines):

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

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

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

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

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

[",<..>,", ",<..>,", "<,,,.>"] (list syntax depends on language)

Note that (at least in this example) there are multiple sets of animals than can work. But remember you only need to output any one valid solution, if one exists. The number of animals or number of distinct animals does not matter.

For inputs such as X = 3, Y = 3 or X = 1, Y = 5 where there is no solution, the output will always be

~<.,,>~~

perhaps in a single-element list.

The shortest code in bytes wins.

\$\endgroup\$
2
  • 7
    \$\begingroup\$ The koala looks just like that :-) \$\endgroup\$
    – Luis Mendo
    Commented Nov 26, 2016 at 0:19
  • \$\begingroup\$ I created a small programm that outputs the number of combinations for each pair (X, Y). Unfortunately, I could only run it up until (128, 128) because that's about the maximum for __int128 and I was too lazy to use a bignum library. Here is the CSV dump: pastebin.com/ght5xkRu the first row and column are the X and Y values \$\endgroup\$
    – user30382
    Commented Nov 26, 2016 at 13:57

3 Answers 3

5
\$\begingroup\$

Ruby, 139 bytes

Lambda function, takes x and y as arguments and returns a string

->x,y{c=y-2*n=y-(x>y ?1:0)>>1
x+=-c/2*s=[x-n,c*3].max
x<n||x>n*2?'~<.,,>~~':',<..>, '*(x-n)+'<.,.> '*(2*n-x)+"<%s.> "*c%[?,*s-=c/2*3,?,*3]}

If a solution exists, it can be done with all koalas+commapillars or all koalas+crabs.

The principle is to use a minimum of commapillars. If the number is odd, we use 1 commapillar. if even we use 0 commapillars, unless there are more commas than periods, in which case we use 2.

The number of periods used in noncommapillars (crabs + koalas) is necessarily even, and the number of noncommapillars is half (number of periods)-(number of commapillars). If there are insufficient commas for all koalas, or too many for all crabs, no solution is possible. Otherwise, we return a solution.

Commented in test program

uses "fail" instead of chameleon for clarity

f=->x,y{c=y-2*n=y-(x>y ?1:0)>>1
#n=noncommapillars=y>>1 as they have 2 periods. c=commapillars=y-2*n, 1 for odd y, 0 for even y.
#if x>y there are too many commas to have 0 commapillars for even y. noncommapillars= y-1 >> 1, so 2 commapillars

x+=-c/2*s=[x-n,c*3].max
# s=number of commas allocated to commapillars. x-n to allow all noncommapillars to be koalas, but at least 3 per commapillar.
#-c/2 == -1 if there are commapillars, 0 if not (Ruby truncates toward -inf). Subtract commas for commapillars from x if necessary

x<n||x>n*2?'fail':',<..>, '*(x-n)+'<.,.> '*(2*n-x)+"<%s.> "*c%[?,*s-=c/2*3,?,*3]}
#if x<n (insufficient commas for all koalas) or x>n*2 (too many for all crabs) return fail. Else...
#return string off crabs, koalas, and (using % operator like sprintf) c commapillars (0..2), the second with 3 commas (if present) and the first with the rest.  



10.times{|j|10.times{|i|puts "%-20s %s"%[?.*j+?,*i,f[i,j]]}}
#all x,y from 0..9

Output

,                    fail
,,                   fail
,,,                  fail
,,,,                 fail
,,,,,                fail
,,,,,,               fail
,,,,,,,              fail
,,,,,,,,             fail
,,,,,,,,,            fail
.                    fail
.,                   fail
.,,                  fail
.,,,                 <,,,.>
.,,,,                <,,,,.>
.,,,,,               <,,,,,.>
.,,,,,,              <,,,,,,.>
.,,,,,,,             <,,,,,,,.>
.,,,,,,,,            <,,,,,,,,.>
.,,,,,,,,,           <,,,,,,,,,.>
..                   fail
..,                  <.,.>
..,,                 ,<..>,
..,,,                fail
..,,,,               fail
..,,,,,              fail
..,,,,,,             <,,,.> <,,,.>
..,,,,,,,            <,,,,.> <,,,.>
..,,,,,,,,           <,,,,,.> <,,,.>
..,,,,,,,,,          <,,,,,,.> <,,,.>
...                  fail
...,                 fail
...,,                fail
...,,,               fail
...,,,,              <.,.> <,,,.>
...,,,,,             <.,.> <,,,,.>
...,,,,,,            <.,.> <,,,,,.>
...,,,,,,,           <.,.> <,,,,,,.>
...,,,,,,,,          <.,.> <,,,,,,,.>
...,,,,,,,,,         <.,.> <,,,,,,,,.>
....                 fail
....,                fail
....,,               <.,.> <.,.>
....,,,              ,<..>, <.,.>
....,,,,             ,<..>, ,<..>,
....,,,,,            fail
....,,,,,,           fail
....,,,,,,,          <.,.> <,,,.> <,,,.>
....,,,,,,,,         <.,.> <,,,,.> <,,,.>
....,,,,,,,,,        <.,.> <,,,,,.> <,,,.>
.....                fail
.....,               fail
.....,,              fail
.....,,,             fail
.....,,,,            fail
.....,,,,,           <.,.> <.,.> <,,,.>
.....,,,,,,          <.,.> <.,.> <,,,,.>
.....,,,,,,,         <.,.> <.,.> <,,,,,.>
.....,,,,,,,,        <.,.> <.,.> <,,,,,,.>
.....,,,,,,,,,       <.,.> <.,.> <,,,,,,,.>
......               fail
......,              fail
......,,             fail
......,,,            <.,.> <.,.> <.,.>
......,,,,           ,<..>, <.,.> <.,.>
......,,,,,          ,<..>, ,<..>, <.,.>
......,,,,,,         ,<..>, ,<..>, ,<..>,
......,,,,,,,        fail
......,,,,,,,,       <.,.> <.,.> <,,,.> <,,,.>
......,,,,,,,,,      <.,.> <.,.> <,,,,.> <,,,.>
.......              fail
.......,             fail
.......,,            fail
.......,,,           fail
.......,,,,          fail
.......,,,,,         fail
.......,,,,,,        <.,.> <.,.> <.,.> <,,,.>
.......,,,,,,,       <.,.> <.,.> <.,.> <,,,,.>
.......,,,,,,,,      <.,.> <.,.> <.,.> <,,,,,.>
.......,,,,,,,,,     <.,.> <.,.> <.,.> <,,,,,,.>
........             fail
........,            fail
........,,           fail
........,,,          fail
........,,,,         <.,.> <.,.> <.,.> <.,.>
........,,,,,        ,<..>, <.,.> <.,.> <.,.>
........,,,,,,       ,<..>, ,<..>, <.,.> <.,.>
........,,,,,,,      ,<..>, ,<..>, ,<..>, <.,.>
........,,,,,,,,     ,<..>, ,<..>, ,<..>, ,<..>,
........,,,,,,,,,    <.,.> <.,.> <.,.> <,,,.> <,,,.>
.........            fail
.........,           fail
.........,,          fail
.........,,,         fail
.........,,,,        fail
.........,,,,,       fail
.........,,,,,,      fail
.........,,,,,,,     <.,.> <.,.> <.,.> <.,.> <,,,.>
.........,,,,,,,,    <.,.> <.,.> <.,.> <.,.> <,,,,.>
.........,,,,,,,,,   <.,.> <.,.> <.,.> <.,.> <,,,,,.>
\$\endgroup\$
0
4
\$\begingroup\$

Befunge, 249 218 bytes

&::00p&::00g\`-2/:20p2*-3*:30p\20g-`:!00g20g-*\30g*+:30g-v>:#,_@
"~<.,,>~~"0_v#\g03+`g050`\0:-g02\p05:-\*2g02:-*/6+3g03p04<^
$"<">:#,_40p>:!#|_3-0" >.,,"40g3>3g#<\#-:#1_
0" ,>..<,">:#,_$>:!#|_1-
#@_1-0" >.,.<">:#,_$>:!

Try it online!

This is now based on the algorithm in the Ruby answer by Level River St, which provided greater scope for golfing and a significant reduction in size compared to my original solution.

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

C#6, 321 303 bytes

using System.Linq;string F(int x,int y)=>S(x,y)??"~<.,,>~~";string S(int x,int y)=>x<0|y<0?null:y<1?x<1?"":null:y*3>x?S(x-1,y-2)!=null?S(x-1,y-2)+"<.,.> ":S(x-2,y-2)!=null?S(x-2,y-2)+",<..>, ":null:string.Concat(new int[y].Select((_,k)=>k<1?C(x-y*3+3):C(3)));string C(int x)=>$"<{new string(',',x)}.> ";

Call F(). The other two functions are helpers. repl.it demo

// Coalesce failed combinations with commaleon
string F(int x,int y)=>S(x,y)??"~<.,,>~~";
// Get successful combination or null
string S(int x,int y)=>
    x<0|y<0
        // Fail: Out of range
        ?null
        :y<1
            ?x<1
                // Successful: All commas and periods accounted for
                ?""
                // Fail: Not enough periods for commas
                :null
            :y*3>x
                // Not all commapillars
                ?S(x-1,y-2)!=null
                    // Try koala
                    ?S(x-1,y-2)+"<.,.> "
                    // Try crab
                    :S(x-2,y-2)!=null
                        ?S(x-2,y-2)+",<..>, "
                        // Epic fail
                        :null
                // All commapillars
                :string.Concat(new int[y].Select((_,k)=>k<1
                    // This commapillar takes most of commas
                    ?C(x-y*3+3)
                    // The rest each takes 3
                    :C(3)));
// Generate single commapillar
string C(int x)=>$"<{new string(',',x)}.> ";
\$\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.