Do you want to code a snowman?

156

35

Here is a simple ASCII art snowman:

_===_
(.,.)
( : )
( : )

Let's make him some friends. This will be the general pattern for our ASCII art snowpeople:

 HHHHH
 HHHHH
X(LNR)Y
X(TTT)Y
 (BBB)

The leading spaces and the parentheses are always the same for all snowpeople. The different letters represent sections of the pattern that can individually change. Each section has exactly four presets for what ASCII characters can fill it. By mixing and matching these presets for all eight sections, we can make a variety of snowpeople.

All Presets

(Notice that spaces are put on otherwise empty lines so the section shape is always correct.)

H is for Hat

  1. Straw Hat

         
    _===_
  2. Mexican Hat

     ___ 
    .....
    
  3. Fez

      _  
     /_\ 
    
  4. Russian Hat

     ___ 
    (_*_)
    

N is for Nose/Mouth

  1. Normal ,

  2. Dot .

  3. Line _

  4. None

L is for Left Eye

  1. Dot .

  2. Bigger Dot o

  3. Biggest Dot O

  4. Closed -

R is for Right Eye

(Same list as left eye.)

X is for Left Arm

  1. Normal Arm

     
    <
  2. Upwards Arm

    \
     
  3. Downwards Arm

     
    /
  4. None

     
     

Y is for Right Arm

  1. Normal Arm

     
    >
  2. Upwards Arm

    /
     
  3. Downwards Arm

     
    \
  4. None

     
     

T is for Torso

  1. Buttons :

  2. Vest ] [

  3. Inward Arms > <

  4. None

B is for Base

  1. Buttons :

  2. Feet " "

  3. Flat ___

  4. None

Challenge

Write a program that takes in an eight character string (via stdin or command line) in the format HNLRXYTB, where each letter is a digit from 1 to 4 that denotes which preset to use for the corresponding section of the snowperson. Print the full snowperson to stdout.

For example, the input 11114411 is the snowman at the top of the page. (First 1: he has a straw hat, second 1: he has a normal nose, etc.)

Another example, the snowperson for input 33232124:

   _
  /_\
\(o_O)
 (] [)>
 (   )

Details

  • Any amounts and combinations of leading/trailing spaces and leading/trailing newlines are allowed as long as...

    • the snowperson has all their sections arranged correctly with respect to one another, and
    • there are never more than 64 total whitespace characters (the general pattern is only 7×5, so you probably won't hit this limit).

    You don't need to print rows/columns of the pattern if they only contain whitespace. e.g. the empty line of the straw hat is not required.

  • You must use the ordering of the parts as they are given above.

  • Instead of a program, you may write a function that takes the digit string as an argument. The output should be printed normally or returned as a string.

  • You may treat the input as an integer instead of a string if preferred.

Scoring

The shortest code in bytes wins.

Bonus question: Which of the 65536 distinct snowpeople is your favorite?

Calvin's Hobbies

Posted 2015-05-06T05:34:04.403

Reputation: 48 376

18

I like the angel 14441133. Alternatively the small-eyed four-armed monster. Your pick.

– Sp3000 – 2015-05-06T08:28:53.897

14Does it have to be a snowman? – None – 2015-05-06T13:14:35.993

50It doesn't have to be a snowman. (Disclaimer: It may have to be a snowman) – Joshpbarron – 2015-05-06T13:24:36.723

44I approve of this question. – None – 2015-05-07T04:42:37.160

3

The occasional witty comment is nice, but for extended discussion please use chat instead of comments. I've cleaned this up a bit.

– Martin Ender – 2015-05-07T17:11:16.113

28Question to do next: "The code never bothered me anyway" – Calvin's Hobbies – 2015-05-09T19:19:50.347

What if I write a parser/compiler for a new language (say "Snowman++"), which only requires me to declare all the possible variations of eyes, arms, legs, etc.? Would you count the size of that parser/compiler too, or just the size of the "source code" for that language, which could be as low as 69 for the given variations: === ..... /\ (*),. .oO-</\ >/\ : ] [> < : " "___ – Mladen B. – 2015-08-14T11:44:51.083

1

@MladenB. That's a frowned upon loophole. Besides, languages have to exist before the challenge to win. (see here)

– Calvin's Hobbies – 2015-08-14T18:50:52.137

Answers

33

CJam, 135 134 132 130 126 125 bytes

0000000: 4e22285b200a5c225f2a295c2d2e2f6f2c3e4f3a3c3d5d225f  N"([ .\"_*)\-./o,>O:<=]"_
0000019: 2422dd7382d6bfab28707190992f240c362ee510262bd07a77  $".s....(pq../$.6...&+.zw
0000032: 08556de9dcdb566c676817c2b87f5ecb8bab145dc2f2f76e07  .Um...Vlgh....^....]...n.
000004b: 22323536624b623224663d4e2f7b5f2c342f2f7d25723a7e2e  "256bKb2$f=N/{_,4//}%r:~.
0000064: 3d2828342423346222205f0a20222e2a6f6f736572372f4e2a  =((4$#4b" _. ".*ooser7/N*

To create the file on your machine, execute xxd -r > snowman.cjam, paste the reversible hexdump from above, press Enter and finally Ctrl + D.

Alternatively, you can try the code online using the CJam interpreter.

Bonus

My favorite snowman is Olaf:

$ LANG=en_US cjam snowman.cjam <<< 12222212

 _===_
\(o.o)/
 ( : ) 
 (" ")

Winter's a good time to stay in and cuddle, but put me in summer and I'll be a… happy snowman!

Idea

The hex string

dd7382d6bfab28707190992f240c362ee510262bd07a7708
556de9dcdb566c676817c2b87f5ecb8bab145dc2f2f76e07

encodes the possible choices for all parts of the snowman, including the fixed ones. Let's call this string P.

To decode it, we convert P (here treated as an array of integers) from base 256 to base 20 and replace each of the resulting integers by the corresponding character of the string M:

([ 
"_*)\-./o,>O:<=]

This results in the string T:

/(_*_)"_===_/....., /_\ 
 ,._
-.oO
-.oO
   <\  /
   >/  \
    : ] [> <
    : " "___
 ((()

The first line encodes all hat choices, the last all fixed body parts. The other lines contain the 28 variable body parts.

We split T at linefeeds and divide the strings of the resulting array into four parts of equal length. Then, we read the input from STDIN, push the array of its digits in base 10 and select the corresponding elements of the split strings. We take advantage of the fact that arrays wrap around in CJam, so the element at index 4 of an array of length 4 is actually the first element. The last divided string does not correspond to any input, so it will get selected entirely.

We handle the hat by shifting the first element out of the resulting array. The index in M of first character, read as a base 4 number, reveals the number of spaces and underscores in the first line of the hat. We print those characters, a linefeed, a space and the remainder of the shifted string. Then, we push an additional linefeed on the bottom of the stack.

For the body parts, we concatenate the string corresponding to all of them. Let's call this string S. To assemble the body parts, we perform transliteration: we take each character of the string M, compute its index in sort(M) and replace it by the corresponding character of S. We take advantage of the fact that the transliteration operator automatically pads S to match the length of sort(M) by repeating the last character of S as many times as necessary.

Finally, we divide the resulting string into substrings of length 7 and place a linefeed between each pair of substrings.

Code

Suppose that the variables M and P contain the strings M and P.

N        e# Push a linefeed.
M_$      e# Push M and a sorted copy.
P256bKb  e# Push P and convert it from base 256 to base 20.
2$       e# Push a copy of M.
f=       e# Compute T by retrieving the proper chars from M.
N/       e# Split T at linefeeds.
{_,4//}% e# Divide each string into four substrings of equal length.
r:~      e# Read a number from STDIN and push the array of its digits in base 10.
.=       e# Get the corresponding chunks from T.
((       e# Shift out the first string and that string's first character.
4$#      e# Find its index in M.
4b       e# Compute its digits in base 4.
" _
 ".*     e# Repeat the space and underscore that many times in place.
oo       e# Print the result and the shifted string.
s        e# Flatten the remainder of the array. This pushes S.
er       e# Perform transliteration.
7/       e# Split into chunks of length 7.
N*       e# Join using linefeeds.

Dennis

Posted 2015-05-06T05:34:04.403

Reputation: 171 923

58

JavaScript ES6, 210 208 bytes

s=>` 0
8(213)9
4(6)5
 (7)`.replace(/\d/g,p=>`_===_1 ___
 .....1  _
  /_\\1 ___
 (_*_)1,1.1_1 1.1o101-1.1o101-1<1 1/1 1>1 1\\1 1 : 1] [1> <1   \
1 : 1" "1___1   1 1\\1 1 1 1/1 1 `.split(1)[s[p>7?p-4:p]-1+p*4])

This is an anonymous function; you use it by executing ([function code])('42232124'). The most aggravating part of this was the arms, which take up 2 lines, so I had to include code for both top and bottom.

The Stack Snippet below has ungolfed, un-ES6-ified, commented code. And you can use it to easily test the code and try out different combinations. Edit: I'm having way too much fun with this. I've added several new features, including a way to generate a random snowman.

var f=function(s){
  return' 0\n8(213)9\n4(6)5\n (7)' // Start with a placeholder string with all the static components
    .replace(/\d/g,function(p){ // Go through each placeholder number to replace it with its value
    // The massive string below holds all the possible body parts, separated by 1 for easy splitting.
    // The two at the end are for the top of the arms
    return'_===_1 ___\n .....1  _\n  /_\\1 ___\n (_*_)1,1.1_1 1.1o101-1.1o101\
-1<1 1/1 1>1 1\\1 1 : 1] [1> <1   1 : 1" "1___1   1 1\\1 1 1 1/1 1 '.split(1)
    [s[p>7?p-4:p]-1 // Get the value from the input string. If the current body part
                    // is the top of the two-line arms (8 or 9), drop it down to 4 or 5
                    // Subtract 1 to account for the 0-indexed array.
     +p*4] // multiply by 4 to skip to the relevant code
  })
}

// Code for the interactive version follows
// http://codepen.io/hsl/pen/bdEgej
function updateRadios(){$('input[type="radio"]').each(function(){if($(this).is(":checked")){var t=$(this).data("p"),i=$(this).data("v");input[t]=i}}),inputS=input.join(""),update()}var input=[],inputS=$("#code").val(),update=function(){$("#p").text(f(inputS)),$("#code").val(inputS)};$('input[type="radio"]').change(updateRadios),$("#code").keyup(function(){inputS=$(this).val(),update()}),updateRadios(),$("#random").click(function(){for(var t=0;8>t;t++)$("div:eq("+t+") input:eq("+Math.floor(4*Math.random())+")").prop("checked",!0);updateRadios()});
body{font-family:sans-serif}h2{font-size:18px;font-weight:400}label{display:block}div{display:inline-block;margin:0 10px}#code{width:70px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div><h2>Hat</h2><label><input type="radio" name="p1" data-p="1" data-v="1"> Straw hat</label><label><input type="radio" name="p1" data-p="1" data-v="2"> Mexican hat</label><label><input type="radio" name="p1" data-p="1" data-v="3"> Fez</label><label><input type="radio" name="p1" data-p="1" data-v="4" checked> Russian hat</label></div><div><h2>Nose/mouth</h2><label><input type="radio" name="p2" data-p="2" data-v="1"> Normal</label><label><input type="radio" name="p2" data-p="2" data-v="2" checked> Dot</label><label><input type="radio" name="p2" data-p="2" data-v="3"> Line</label><label><input type="radio" name="p2" data-p="2" data-v="4"> None</label></div><div><h2>Left eye</h2><label><input type="radio" name="p3" data-p="3" data-v="1"> Dot</label><label><input type="radio" name="p3" data-p="3" data-v="2" checked> Bigger dot</label><label><input type="radio" name="p3" data-p="3" data-v="3"> Biggest dot</label><label><input type="radio" name="p3" data-p="3" data-v="4"> Closed</label></div><div><h2>Right eye</h2><label><input type="radio" name="p4" data-p="4" data-v="1"> Dot</label><label><input type="radio" name="p4" data-p="4" data-v="2"> Bigger dot</label><label><input type="radio" name="p4" data-p="4" data-v="3" checked> Biggest dot</label><label><input type="radio" name="p4" data-p="4" data-v="4"> Closed</label></div><div><h2>Left arm</h2><label><input type="radio" name="p5" data-p="5" data-v="1"> Normal</label><label><input type="radio" name="p5" data-p="5" data-v="2" checked> Upwards</label><label><input type="radio" name="p5" data-p="5" data-v="3"> Downwards</label><label><input type="radio" name="p5" data-p="5" data-v="4"> None</label></div><div><h2>Right arm</h2><label><input type="radio" name="p6" data-p="6" data-v="1" checked> Normal</label><label><input type="radio" name="p6" data-p="6" data-v="2"> Upwards</label><label><input type="radio" name="p6" data-p="6" data-v="3"> Downwards</label><label><input type="radio" name="p6" data-p="6" data-v="4"> None</label></div><div><h2>Torso</h2><label><input type="radio" name="p7" data-p="7" data-v="1"> Buttons</label><label><input type="radio" name="p7" data-p="7" data-v="2" checked> Vest</label><label><input type="radio" name="p7" data-p="7" data-v="3"> Inward arms</label><label><input type="radio" name="p7" data-p="7" data-v="4"> None</label></div><div><h2>Base</h2><label><input type="radio" name="p8" data-p="8" data-v="1"> Buttons</label><label><input type="radio" name="p8" data-p="8" data-v="2"> Feet</label><label><input type="radio" name="p8" data-p="8" data-v="3"> Flat</label><label><input type="radio" name="p8" data-p="8" data-v="4" checked> None</label></div><br><button id="random">Randomize</button><pre id="p"></pre><input type="text" id="code">

NinjaBearMonkey

Posted 2015-05-06T05:34:04.403

Reputation: 8 395

2+1 Very clever, so much better than mine – edc65 – 2015-05-07T15:02:45.113

21The 'GUI' is pretty darn cool. – topher – 2015-05-08T15:56:00.673

You can save 2 bytes by using your "un-ES6-fied" code instead of p*4+(s[p&gt;7?p-4:p]-1) and another 2 bytes by making the function anonymous (which is allowed by default).

– Dennis – 2015-05-10T04:47:01.107

@Dennis Thanks! I had actually subtracted the first one from my byte count but forgot to change the code. – NinjaBearMonkey – 2015-05-10T15:00:19.757

7Sweet, check out the 8-eyed spider snowman: 22112333 – Claudiu – 2015-05-11T16:57:59.217

1I like the sleeping Russian owl: 41444442 – ETHproductions – 2015-10-07T16:18:36.117

... 22111131 ... – wizzwizz4 – 2015-12-29T12:08:52.777

29

CJam, 164 bytes

Generates the snowman left-to-right, top-to-bottom. This eliminates the need for any kind of string joining or repositioning operations, as I just leave every piece of the snowman on the stack. And then, due to the automatic stack dump at the end of programs:

CJam wants to build a snowman!

q:Q;SS"
 _===_,___
 ....., _
  /_\,___
 (_*_)"',/0{Q=~(=}:G~N" \ "4G'(".oO-"_2G",._ "1G@3G')" / "5GN"< / "4G'(" : ] [> <   "3/6G')"> \ "5GNS'(" : \" \"___   "3/7G')

Try it online.

Bonus

Thinking outside the box! 32443333 gives a snow(wo)man bride. You've gotta try a bit to see it, but there are the inward arms, fez + downwards arms = veil, and the head is actually in the fez/veil. The generally large form is the billowy dress, and the "eyes" and "nose" are folds in the dress.

   _
  /_\
 (-.-) 
/(> <)\
 (___)

Other "eye" choices are a bit risqué...

Runer112

Posted 2015-05-06T05:34:04.403

Reputation: 3 576

14To me, your bonus looks more like a KKK member than a bride. – ace – 2015-05-08T23:44:22.293

23

Python, 276 289 bytes

V='.oO-'
def F(d):
 D=lambda i:int(d[i])-1
 print"  "+("","___"," _ ","___")[D(0)]+"\n "+\
"_. (=./_=._*=.\\__. )"[D(0)::4]+"\n"+\
" \\  "[D(4)]+"("+V[D(2)]+',._ '[D(1)]+V[D(3)]+")"+" /  "[D(5)]+'\n'+\
"< / "[D(4)]+"("+" ]> :    [< "[D(6)::4]+")"+"> \\ "[D(5)]+"\n ("+\
' "_ : _  "_ '[D(7)::4]+")"

This code has 8 extra bytes(\*4) for readability.

Builds the snowman up bit by bit.

Bonus

F("44444432") gives "sleepy russian bear":

  ___    
 (_*_)
 (- -)
 (> <)
 (" ")

Claudiu

Posted 2015-05-06T05:34:04.403

Reputation: 3 662

12Sleepy russian bear is now my favorite too. – Calvin's Hobbies – 2015-05-08T17:32:51.277

1

The top row underscores don't seem to be correct on the fez and russian hats. e.g. It's giving a propellor hat..

– Calvin's Hobbies – 2015-05-09T01:52:01.513

@Calvin'sHobbies: The russian hat was okay, but the fez hat was messed up. I fixed it now and checked all the other cases too. I must be more careful in the future! – Claudiu – 2015-05-11T16:53:22.957

21

Python 2, 354 280 241 261 bytes

def s(g):H,N,L,R,X,Y,T,B=[int(c)-1for c in g];e='.oO-';print(' '*9+'_ _ ___ _ _\n\n\n\n    _. (=./_=._*=.\\__. )')[H::4]+'\n'+' \\  '[X]+'('+e[L]+',._ '[N]+e[R]+')'+' /  '[Y]+'\n'+'< / '[X]+"("+' ]> :    [< '[T::4]+')'+'> \\ '[Y]+'\n ('+' "_ : _  "_ '[B::4]+")"

Calling s('33232124') gives:

   _ 
  /_\ 
\(o_O) 
 (] [)>
 (   )

But my favorites are 44242123 and 41341144:

  ___      ___
 (_*_)    (_*_)
\(o -)    (O,-) 
 (] [)>  <(   )>
 (___)    (   )

Cees Timmerman

Posted 2015-05-06T05:34:04.403

Reputation: 590

1When I do s('33232124') the fez slashes aren't drawn. In fact the bottom half of the hat is missing in a lot of cases. Also, 0 is not one of the options. – Calvin's Hobbies – 2015-05-09T01:49:46.380

@Calvin'sHobbies Thanks, I fixed it. – Cees Timmerman – 2015-05-09T13:09:32.540

20

CJam, 150 145 bytes

Base convert all the things!

"b8li'
U9gN;|"125:Kb8bl:~f="r  pL|P3{cR`@L1iT"Kb21b"G.HMtNY7VM=BM@$^$dX8a665V"KbFb"=_./ <[(*-oO,\":"f=_"/<[(""\>])"er+4/f=.=7/N*

SE mangles unprintables, so here is a copy on Pastebin. Make sure you copy the "RAW Paste Data" part, not the part next to line numbers. You can try it online, but the permalink may not work in some browsers.

Explanation

The "b8li'U9gN;|"125:Kb8bp part generates the array

[1 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 2 1 3 0 5 4 0 6 6 6 0 5 0 0 7 7 7 0]

which maps each digit of the input to where the digit is used. Anything which is common to all inputs (e.g. leading spaces and ()) is arbitrarily assigned a 0, except the first which is assigned 1 so that base convert can work.

l:~f= then converts each digit to an int and maps accordingly, e.g. for 14441133 we get

[2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 2 4 1 2 1 1 3 3 3 1 2 1 1 4 4 4 1]

"G.HMtNY7VM=BM@$^$dX8a665V"KbFb"=_./ <[(*-oO,\":"f= gives the string

"_=./  /  < /  [<(((((_. _ _     _ __*=._-.oO ,._  \"_ :   : _"

after which we duplicate, replace /<[( with \>]) and append to give a long string. Then we split the string into groups of 4 and map according to another array "r pL|P3{cR`@L1iT"Kb21b, thus getting an array of length-4 strings describing all possible options at each cell (e.g. _=./ is all possible options for the second character on the second line, starting from the Russian hat).

Finally we map the options to the inputs accordingly .=, split into rows of length 7 7/ and riffle in some newlines N*.

Test runs

11111111

 _===_ 
 (.,.) 
<( : )>
 ( : )

22222222
  ___  
 ..... 
\(o.o)/
 (] [) 
 (" ")

33333333
   _   
  /_\  
 (O_O) 
/(> <)\
 (___)

44444444
  ___  
 (_*_) 
 (- -) 
 (   ) 
 (   )

Sp3000

Posted 2015-05-06T05:34:04.403

Reputation: 54 224

16

TI-BASIC, 397 bytes

Important: If you want to test this out, download it from here and send that file to your calculator. Do not try to copy the code below into TI-Connect CE's program editor or SourceCoder 3 or something to build and send it to your calculator; in TI-Connect's case, it'll say it has an invalid token. SC3 uses the backslash as a comment delimiter (// starts a comment in SC3; /\/, though, will export as //) and so it won't export the arms and hat and such correctly, causing the program to both display the incorrect body parts and throw an ERROR:DOMAIN every now and then. Fun stuff!

Important #2: I'm too lazy to fix the download at the moment, so when you transfer it to your calc, change the 7 on the third line from the bottom to X+6. The code below is fixed if you need to compare.

Input Str9
seq(inString("1234",sub(Str9,I,1)),I,1,length(Ans→L1
"      ___   _   ___ →Str1
"_===_..... /_\ (_*_)→Str2
",._ →Str3
"•oO-→Str4
"<\/ →Str5
">/\ →Str6
" : ] [> <   →Str7
" : ¨ ¨___   →Str8
"Str1Str2Str3Str4Str5Str6Str7Str8→Str0
For(X,3,5
Output(X,2,"(   )
End
L1
Output(3,3,sub(Str4,Ans(3),1)+sub(Str3,Ans(2),1)+sub(Str4,Ans(4),1
Ans(5
Output(4-(Ans=2),1,sub(Str5,Ans,1
L1(6
Output(4-(Ans=2),7,sub(Str6,Ans,1
L1-1
For(X,1,2
Output(X+3,3,sub(expr(sub(Str0,X+6,1)),1+3Ans(X+6),3
Output(X,2,sub(expr(sub(Str0,X,1)),1+5Ans(1),5
End

Bonus: I'm particularly fond of 12341214.

 _===_
 (O.-)/
<( : )
 (   )

Some notes:

  • It can definitely be golfed more, no question about that. I'm nearly positive that I can combine a majority, if not all, of the outputting into a single For( loop. Also, I'm pretty sure that I can merge some strings together.
  • In Str4 (the eyes) I use the "plot dot" ([2ND] → [0]CATALOG → [3]θ → scroll down, it's between ﹢ (small plus) and · (interpunct)) as opposed to a period so that the eyes don't line up with the comma, because that looks weird as hell.
  • In Str8 (base) I had to use a diaeresis (¨) instead of double quotes because there's no way to escape characters in TI-BASIC, and double quotes are used to start/end strings.
  • In TI-BASIC, there's no need to close parentheses and brackets if they're followed by a colon, newline or → (used for var assignment), and double quotes (strings) can stay unclosed when followed by a newline or →.

M. I. Wright

Posted 2015-05-06T05:34:04.403

Reputation: 715

1First, in the second line, length(Ans should be length(Str9; second, have you tried combining Str3 through Str6 into a single string? – lirtosiast – 2015-05-17T17:31:06.500

Oh, whoops! I think that's fixed in the download, though. Besides that, I haven't looked at this much since I made it, but I did mention that I could probably merge some strings together; I'll look into that sometime today/this week. – M. I. Wright – 2015-05-17T17:35:52.280

15

C, 280 272 264 bytes

Only partially golfed at this point, but this is a fun challenge.

#define P(n)[s[n]&3],
f(char*s){printf("  %.3s\n %.5s\n%c(%c%c%c)%c\n%c(%.3s)%c\n (%.3s)",
"___   ___ _"+*s%4*3,"(_*_)_===_..... /_\\"+*s%4*5,"  \\ "P(4)"-.o0"P(2)    
" ,._"P(1)"-.o0"P(3)"  /"P(5)" < /"P(4)"    : ] [> <"+s[6]%4*3," > \\"P(5)
"    : \" \"___"+s[7]%4*3);}

(With some extra \n for readability.) I expect the define should go away with further golfing.

A more readable version is

#define P(n)[s[n]&3],
f(char *s) {
  printf("  %.3s\n"
         " %.5s\n"
         "%c(%c%c%c)%c\n"
         "%c(%.3s)%c\n"
         " (%.3s)",
         "___   ___ _"+*s%4*3,                  /* Top of hat. */
         "(_*_)_===_..... /_\\"+*s%4*5,         /* Lower hat. */
         "  \\ "P(4)                            /* Upper left arm. */
         "-.o0"P(2)                             /* Left eye. */
         " ,._"P(1)                             /* Nose. */
         "-.o0"P(3)                             /* Right eye. */
         "  /"P(5)                              /* Upper right arm. */
         " < /"P(4)                             /* Lower left arm. */
         "    : ] [> <"+s[6]%4*3,               /* Torso. */
         " > \\"P(5)                            /* Lower right arm. */
         "    : \" \"___"+s[7]%4*3              /* Base. */
         );
}

CL-

Posted 2015-05-06T05:34:04.403

Reputation: 711

10

JavaScript, 489 (without newlines and tabs)

x=' ';
d="   ";
h=['\n_===_',' ___ \n.....','  _  \n /_\\ ',' ___ \n(_*-)'];
n=[',','.','_',x];
e=['.','o','O','-'];
y=['>',,'\\',x];
u=['<',,'/',x];
t=[' : ','[ ]','> <',d;
b=[' : ','" "',"___",d];

j=process.argv[2].split('').map(function(k){return parseInt(k)-1});
q=j[4]==1;
w=j[5]==1;

console.log([
    h[j[0]].replace(/(.*)\n(.*)/g, " $1\n $2"),
    (q?'\\':x)+'('+e[j[2]]+n[j[1]]+e[j[3]]+')'+(w?'/':x),
    (!q?u[j[4]]:x)+'('+t[j[6]]+')'+(!w?y[j[5]]:x),
    x+'('+b[j[7]]+')'].join('\n'));

run with node snowman.js 33232124

AllTheTime

Posted 2015-05-06T05:34:04.403

Reputation: 201

6Welcome to Code Golf! A few pointers: You may not need a parseInt call, since subtraction automatically tries to cast string operands to numbers. Also, you can get rid of the function wrapping and just lead with i=process.argv[2], unless you're using it for recursion or variable scoping. Additionally, you can get rid of s entirely and just do console.log([ ... ].join('\n')). – apsillers – 2015-05-06T12:55:31.820

3Actually, you could do away with the input string-to-array conversion entirely if you put a leading comma in each of your arrays to increase the index of each item. It adds 7 , characters, but it allows you to remove more than 50. Finally, one very finicky optimization would be using q=j[4]-1 instead of q=j[4]==1 (and then flipping your use of q and !q). This will cause q to be 0 (a falsey value) when j[4] is 1, and otherwise a truthy nonzero value. This is the exact opposite of your current true/false values, so you simply switch q and !q. – apsillers – 2015-05-06T13:15:05.417

Sorry for the mound of feedback on your first answer! I personally find revising my submissions to be one of the most fun parts of golfing; my apologies if you don't share my feeling. :) – apsillers – 2015-05-06T13:18:15.857

@apsillers your feedback is greatly appreciated! I was about to go to sleep last night and then wrote this for fun with the full intention of widding it down to the simplest possible later. I'll be doing some edits tonight! – AllTheTime – 2015-05-06T19:24:32.950

9

Pyth, 203 bytes

M@GCHgc"  ___

  ___
   _"bhzgc" (_*_)
 _===_
 .....
  /_\\"bhzs[g"  \ "@z4\(g"-.oO"@z2g" ,._"@z1g"-.oO"@z3\)g"  / "@z5)s[g" < /"@z4\(gc"   
 : 
] [
> <"b@z6\)g" > \\"@z5)++" ("gc"   
 : 
\" \"
___"bez\)

Lol. Try it online: Pyth Compiler/Executor

Explanation

First I define a helper function g, which takes a list and a char as input, converts the char into its ASCII-value and takes correspondent element (modular wrapping).

M@GCH  def g(G,H): return G[ord(H)]

The other things is just printing line by line. For instance the first line is:

 c"  ___\n\n  ___\n   _"b     split the string "  ___\n\n  ___\n   _" at "\n"
                         hz   first char in input
g                             apply g and print

Btw. I experimented a little bit with .F"{:^7}", which centers a string. Using it, I could save a few spaces in my code, but it doesn't save any bytes at the end.

Jakube

Posted 2015-05-06T05:34:04.403

Reputation: 20 252

9

C, 212 bytes

d;main(){char*t="##3#b#b3#bbb3#b#b##\r#3b1#+3@12b3@1b-3@1_b3b1#,#\r7#_##+51rR04/1b#61rR0,8#2##\r7?#2#+9#`A#9=###9#^?#,8A#_#\r#+:#%b#:=#b#:#%b#,#",p[9];for(gets(p);d=*t++;putchar(d-3))d=d<51?d:(p[d-51]-53)[t+=4];}

A readable version:

d;
main()
{
    char *t = "##3#b#b3#bbb3#b#b##\r"
              "#3b1#+3@12b3@1b-3@1_b3b1#,#\r"
              "7#_##+51rR04/1b#61rR0,8#2##\r"
              "7?#2#+9#`A#9=###9#^?#,8A#_#\r"
              "#+:#%b#:=#b#:#%b#,#",
        p[9]; // 9 bytes is just enough for the input string of length 8

    for (gets(p); d = *t++; putchar(d-3))
        d = d < 51 ? d : (p[d - 51] - 53)[t += 4];
}

I took the idea from the answer by Reto Koradi. There were several fun improvements I did, which may warrant posting a separate answer:

  • Converted from function to program (+10)
  • Moved newlines into the control string (-7)
  • Added 3 to all character codes to have fewer escaped chars like \" (-3)
  • Reading from the string with autoincrement; also replaced t[i++] by *t++ (-4)
  • Replaced while by for; removed {} (-4)
  • Simplified loop termination: reading until \0 (-9)
  • Transformed t[...],t+=4 to (...)[t+=4] to eliminate the comma operator (-1)

Why all that trouble? To share my favorite one, snow ghost:

   _
  /_\
\(. .)/
 (   )
 (___)

anatolyg

Posted 2015-05-06T05:34:04.403

Reputation: 6 787

8

R, 436 437 bytes

Here's my first try on , using R which isn't the shortest but still fun. At least I'm beating JavaScript (for now)...

H=c("_===_"," ___\n .....","  _\n  /_\\"," ___\n (_*_)")
N=c(",",".","_"," ")
L=c(".","o","O","-")
X=c(" ","\\"," "," ")
S=c("<"," ","/"," ")
Y=c(" ","/"," ","")
U=c(">"," ","\\","")
T=c(" : ","] [","> <","   ")
B=c(" : ","\" \"","___","   ")
f=function(x){i=as.integer(strsplit(x,"")[[1]]);cat(" ",H[i[1]],"\n",X[i[5]],"(",L[i[3]],N[i[2]],L[i[4]],")",Y[i[6]],"\n",S[i[5]],"(",T[i[7]],")",U[i[6]],"\n"," (",B[i[8]], ")",sep="")}

Testing:

> f("12344321")
 _===_
 (O.-) 
 (] [)\
 ( : )

I actually struggled with X and Y being multilined but with stuff in between, ended up separating each line in (X, S) and (Y, U).

function and conversion from string to integer are also very verbose.

Edit 436 => 437

Had to fix a missing empty space noticed by @OganM

I could reduce to 428 replacing the line breaks between variables with ;, but the "one-lined" code looks so bad and unreadable I won't be that greedy.

Molx

Posted 2015-05-06T05:34:04.403

Reputation: 181

you need and extra char for the 4th hat – OganM – 2015-05-07T18:54:57.357

@OganM Thanks for that extra byte! :( Fixed. – Molx – 2015-05-07T19:16:18.230

When doing codegolf we generally count each new line as one character (as it is on *nix) as opposed to two (as in Windows). So it shouldn't matter whether you use semicolon or new line. – ace – 2015-05-08T23:54:25.950

@ace Thanks for the tip, good to know! – Molx – 2015-05-09T02:56:31.707

8

Haskell, 361 306 289 bytes

o l a b=take a$drop((b-1)*a)l
n="\n"
p i=id=<<["  ",o"    \n _===____ \n ..... _  \n  /_\\ ___ \n (_*_)"11a,n,o" \\  "1e,o"(.(o(O(-"2c,o",._ "1 b,o".)o)O)-)"2d,o" /  "1f,n,o"< / "1e,o"( : )(] [)(> <)(   )"5g,o"> \\ "1f,n," (",o" : )\" \")___)   )"4h]where[a,b,c,d,e,f,g,h]=map(read.(:[]))i

Usage:

putStrLn $ p "12333321"

 _===_
 (O.O) 
/(] [)\
 ( : )

How it works: index every element of the list of [hat options, left upper arm options, left eye options, ..., base options] with the corresponding input number and concatenate it into a single list. I've split the left and right arm into an upper and lower part, so that I can build the snowman line by line.

My favorite is the classic 11112211.

Edit: switched from list of strings to strings for the parts (hat, eye, ...). Needs a second parameter, the length of the substring to take.

Edit II: extracted common substrings

nimi

Posted 2015-05-06T05:34:04.403

Reputation: 28 202

7

CJam, 200 191 bytes

This can surely be golfed a lot. (Specially if I base encode it). But here goes for starters:

7S*"_===_  ___  .....   _    /_\   ___  (_*_)"+6/2/Nf*",._ "1/".oO-"1/_" <\  /   >/  \  "2/4/~" : ] [> <    : \" \"___   "3/4/~]l~Ab:(]z::=:L0=N4{L=}:K~0='(2K1K3K')5K0=N4K1='(6K')5K1=NS'(7K')

Input goes into STDIN. For example, input 23232223 gives:

  ___ 
 .....
\(o_O)/
 (] [) 
 (___)

Try it online here

Optimizer

Posted 2015-05-06T05:34:04.403

Reputation: 23 401

7

Haskell, 333 bytes

My first submission! Builds the snowman from top to bottom, left to right. I split the arms into two functions for each arm, the part next to head and the part next to the body.

The function s takes a list of integers and concatenates the output of the functions which produce the body parts given correct sublists of the input.

a=y["\n _===_\n","  ___ \n .....\n","   _  \n  /_\\ \n","  ___ \n (_*_)\n"]
d=y",._ "
c=y".oO-"
e=y"< / "
j=y" \\  "
f=y"> \\ "
k=y" /  "
y w n=w!!(n-1)
h=y[" : ","] [","> <","   "]
b=y[" ( : ) \n"," (\" \") \n"," (___) \n"," (   ) \n"]
s(m:x:o:p:n:q:t:l:_)=putStr$a m++j x:'(':c o:d n:c p:')':k q:'\n':e x:'(':h t++')':f q:'\n':b l

It relies on the function

y :: [a] -> Int -> a
y w n=w!!(n-1)

which returns the nth element of the list it is given. This allows for the list of hats in a, as well as things like

k=y" /  "

all of these functions use a beta reduction so their argument is passed as the index to the y function.

Output:

λ> s $ repeat 1

 _===_
 (.,.) 
<( : )>
 ( : ) 

λ> s $ repeat 2
  ___ 
 .....
\(o.o)/
 (] [) 
 (" ") 

λ> s $ repeat 3
   _  
  /_\ 
 (O_O) 
/(> <)\
 (___) 

λ> s $ repeat 4
  ___ 
 (_*_)
 (- -) 
 (   ) 
 (   ) 

Craig Roy

Posted 2015-05-06T05:34:04.403

Reputation: 780

@Calvin'sHobbies Thanks, I think I've fixed that now. – Craig Roy – 2015-05-07T19:23:14.563

7

C, 233 230 bytes

char*t="  0 _ _0 ___0 _ _   0_. (0=./_0=._*0=.\\_0_. ) 4 \\  (2.oO-1,._ 3.oO-)5 /  4< / (6 ]> 6:   6 [< )5> \\  (7 \"_ 7: _ 7 \"_ ) ";i,r,d;f(char*p){while(r++<35){d=t[i]-48;putchar(t[d<0?i:i+p[d]-48]);i+=d<0?1:5;r%7?0:puts("");}}

With newlines and whitespace for better readability:

char* t = "  0 _ _0 ___0 _ _   0_. (0=./_0=._*0=.\\_0_. ) 4 \\  (2.oO-1,._ 3.oO-)5 /  4< / (6 ]> 6:   6 [< )5> \\  (7 \"_ 7: _ 7 \"_ ) ";
i, r, d;
f(char* p)
{
    while (r++ < 35)
    {
        d = t[i] - 48;
        putchar(t[d < 0 ? i : i + p[d] - 48]);
        i += d < 0 ? 1 : 5;
        r % 7 ? 0 : puts("");
    }
}

The whole thing is fairly brute force. It uses a table that contains one entry for each of the 35 (5 lines with length 7) characters. Each entry in the table is either:

  • A constant character: , (, ). Length of table entry is 1 character.
  • Index of body part, followed by the 4 possible characters depending on the part selection in the input. Length of table entry is 5 characters.

The code then loops over the 35 characters, and looks up the value in the table.

Reto Koradi

Posted 2015-05-06T05:34:04.403

Reputation: 4 800

6

Python 3, 349 336 254 251 bytes

So much for doing my thesis.

Here's the content of the file snowman.py:

l='_===_| ___\n .....|  _\n  /_\| ___\n (_*_)| : |] [|> <|   |>| |\| | : |" "|___|   '.split('|')
l[4:4]=' \  .oO-,._ .oO- /  < / '
def s(a):print(' {}\n{}({}{}{}){}\n{}({}){}\n ({})'.format(*[l[4*m+int(a[int('0421354657'[m])])-1]for m in range(10)]))

And this is how I conjure my favourite snowman:

s('11112311')

 _===_ 
\(.,.) 
 ( : )\
 ( : ) 

Explanation

# Create a list containing the 4 * 10 body parts of the snowman in order of drawing:
#   hats,
#   upper left arms, left eyes, noses, right eyes, upper right arms,
#   lower left arms, torso's, lower right arms,
#   bases
l='_===_| ___\n .....|  _\n  /_\| ___\n (_*_)| : |] [|> <|   |>| |\| | : |" "|___|   '.split('|')
l[4:4]=' \  .oO-,._ .oO- /  < / '
# This is the function that draws the snowman
# All the lines of this function are golfed in a single statement, but seperated here for clearity
def s(a):
    # In this list comprehension I put the elements of l that are chosen according to the parameters
    list_comprehension = []
    # m is the number of the body part to draw
    for m in range(10):
        # Get the index for the choice of the m-th bodypart
        # (example: the 2nd bodypart (m = 1: the upper left arm) is in the 4th place of the arguments list)
        choice_index = int('0421354657'[m])
        # n is the parameter of the current bodypart
        n = int(a[choice_index]) - 1
        # Add the body part from list l to the list comprehenseion
        list_comprehension.append( l[4 * m + n] )
    # Print the list comprehension with the static parts
    print(' {}\n{}({}{}{}){}\n{}({}){}\n ({})'.format(*list_comprehension))

Matty

Posted 2015-05-06T05:34:04.403

Reputation: 471

You can remove the space in line 2 between [int(i)] and for. Similarly you can remove the space in line 7 between f(int(i)) and for. Also, in your print() statement you don't need to print the final space - it is not part of the snowman. Finally, change your print() call to a single-line print("{}\n{}({}{}{}){}\n{}({}){}\n ({})".format(*c)). Each of these should save you 1 byte, saving a total of 4 bytes :) – ace – 2015-05-09T00:06:20.143

1Also, instead of using the global variable n, you can define an attribute of function f. So you can replace lines 5-6 with: def f(m):f.n+=1;return l[4*m+int(b[f.n])-1] <newline> f.n=-1. This reduces 3 more bytes. – ace – 2015-05-09T00:14:53.703

1@ace Thanks, never heared of the function attribute before, learned something new! – Matty – 2015-05-09T13:01:56.327

5

JavaScript (ES6), 247

Not as good ad @NinjaBearMonkey's :(

Test in snippet (with Firefox)

S=p=>([h,n,c,d,l,r,t,b,e,x]=[...p,' .oO-',`1_===_1 ___
 .....1  _
  /_\\1 ___
 (_*_)1 : 1] [1> <1   1 : 1" "1___1   `.split(1)],` ${x[h]}
${'  \\  '[l]}(${e[c]+' ,._ '[n]+e[d]})${'  /  '[r]}
${' < / '[l]}(${x[3-~t]})${' > \\ '[r]}
 (${x[7-~b]})`)

// TEST // 

function go()
{
  var n=N.value
  if (/^[1-8]{8}$/.test(n)) {
    s=S(n)
    OUT.innerHTML = s+'\n'+n+'\n\n'+ OUT.innerHTML
  }
  else N.focus()
}
  
<input id=N maxlength=8><button onclick="go()">Test</button>
<pre id=OUT></pre>

edc65

Posted 2015-05-06T05:34:04.403

Reputation: 30 267

5

R 414 Bytes

Slightly modified version of Molx's version

W =c("_===_"," ___\n .....","  _\n  /_\\"," ___\n (_*_)",",",".","_"," ",".","o","O","-"," ","\\"," "," ","<"," ","/"," "," ","/"," ","",">"," ","\\",""," : ","] [","> <","   "," : ","\" \"","___","   ")
f=function(x){i=as.integer(strsplit(x,"")[[1]]);cat(" ",W[i[1]],"\n",W[i[5]+12],"(",W[i[3]+8],W[i[2]+4],W[i[4]+8],")",W[i[6]+20],"\n",W[i[5]+16],"(",W[i[7]+28],")",W[i[6]+24],"\n"," (",W[i[8]+32], ")",sep="")}

Just merged the seperate variables into one. Shawing of some space that was used for X=c( routine.

OganM

Posted 2015-05-06T05:34:04.403

Reputation: 151

1

Java 8, 548 545 bytes

interface M{static void main(String[]a){byte z[]=a[0].getBytes(),t=z[0];System.out.print(" "+(t<50?"     ":t%2>0?" ___ ":"  _  ")+"\n "+(t<50?"_===_":t<51?".....":t<52?" /_\\ ":"(_*_)")+"\n"+(z[4]==50?"\\":" ")+"("+((t=z[2])<50?".":t<51?"o":t<52?"O":"-")+((t=z[1])<50?",":t<51?".":t<52?"_":" ")+((t=z[3])<50?".":t<51?"o":t<52?"O":"-")+")"+(z[5]==50?"/\n":" \n")+(z[4]<50?"<":z[4]%2<1?" ":"/")+"("+((t=z[6])<50?" : ":t<51?"] [":t<52?"> <":"   ")+")"+(z[5]<50?">":z[5]%2<1?" ":"\\")+"\n ("+((t=z[7])<50?" : ":t<51?"\" \"":t<52?"___":"   ")+")");}}

Explanation:

Try it here. (Modified to take a list of arguments)

interface M{                    // Main class
  static void main(String[]a){  //  Main method
    byte z[]=a[0].getBytes(),   //   Take the first argument as byte-array
         t=z[0];                //   And create a temp byte
    System.out.print(           //   Print:
      " "                                                 // A space
      +(t<50?"     ":t%2>0?" ___ ":"  _  ")               // + top of the hat
      +"\n "                                              // + a new-line & space
      +(t<50?"_===_":t<51?".....":t<52?" /_\\ ":"(_*_)")  // + bottom of the hat
      +"\n"                                               // + a new-line
      +(z[4]==50?"\\":" ")                                // + top of left arm
      +"("                                                // + left cheek
      +((t=z[2])<50?".":t<51?"o":t<52?"O":"-")            // + left eye
      +((t=z[1])<50?",":t<51?".":t<52?"_":" ")            // + nose
      +((t=z[3])<50?".":t<51?"o":t<52?"O":"-")            // + right eye
      +")"                                                // + right cheek
      +(z[5]==50?"/\n":" \n")                             // + top of right arm & new-line
      +(z[4]<50?"<":z[4]%2<1?" ":"/")                     // + bottom of left arm
      +"("                                                // + left hip
      +((t=z[6])<50?" : ":t<51?"] [":t<52?"> <":"   ")    // + torso
      +")"                                                // + right hip
      +(z[5]<50?">":z[5]%2<1?" ":"\\")                    // + bottom of right arm
      +"\n ("                                             // + new-line & right base
      +((t=z[7])<50?" : ":t<51?"\" \"":t<52?"___":"   ")  // + feet
      +")");                                              // + left base
  }                             //  End of main-method
}                               // End of class

My favorite:

Try it here.

44114432:
   _  
 (_*_)
 (. .) 
 (> <) 
 (" ")

I don't know why, but it looks kinda cute. Like a bunny with a Russian hat instead of ears.

Kevin Cruijssen

Posted 2015-05-06T05:34:04.403

Reputation: 19 459