Write a function (or a whole program) that outputs (or prints) an ASCII art of the initial position of Mölkky pins.

Output :

    __    __    __
|  (03)__(10)__(04)  |
|  |  (01)  (02)  |  |
|__|  |  |  |  |  |__|
   |__|  |__|  |__|
      |__|  |__|

Rules :

  • This is , so the shortest solution in bytes wins!
  • Trailing spaces are allowed on each line
  • Additional leading spaces (meaning, without counting the already mandatory leading spaces) are allowed only if there are the same number of additional leading spaces in each of the 8 mandatory lines
  • Additional newlines are allowed at the beginning and at the end. These additional lines can contain any number of spaces

Thanks to Arnauld for the ASCII art and his advices concerning the challenge!

Despite the risk of just having to hardcode and/or compress the output, i hope the challenge will be interesting enough!

I intend to post my own answer in Javascript, but since i forced myself to do it without hardcoding, it has become quite long :')

  • 2
    \$\begingroup\$ Where’s the throwing pin? \$\endgroup\$ Commented Jul 5, 2023 at 18:02
  • \$\begingroup\$ Slightly related: Draw a bowling formation \$\endgroup\$
    – xnor
    Commented Jul 5, 2023 at 22:58
  • \$\begingroup\$ @Iamkindofalanguagedev Here it is :) \$\endgroup\$
    – Fhuvi
    Commented Jul 6, 2023 at 8:45
  • \$\begingroup\$ Vaguely related (this one is about scoring rules). \$\endgroup\$
    – Arnauld
    Commented Jul 6, 2023 at 11:21

17 Answers 17


Python 3, 123 bytes

print(b'313a@B$""E""Q$6Q%Q$35Q#'.hex().translate(['__','|  ','  ',*'\n| ','(%02x)']*9)%(*b'	',))

Try it online!


This is a two-step compression. A dictionary coding is first applied so that certain chunks of recurring text is mapped to some number. The specific mapping is defined as follows:

0 -> '(%02x)'
1 -> '__'
2 -> '|  '
3 -> '  '
4 -> '\n'
5 -> '|'
6 -> ' '

The %02xs are converted to their corresponding values at the end by using a % formatting

The compressed string we get after applying the table above is 331331331461010101401010104201010324220303224512222251243651251251243335125123. This string can then be uncompressed by using str.translate().

A nice trick to compress this by roughly half is to use the bytes.fromhex() function, which interprets the string as a sequence of hex digits and converts it to a byte-string. Then to decode, we can use the inverse function, bytes.hex(). Fortunately, all of the hex digits are below 8, so we can represent all the bytes directly without using any escape codes.

  • 2
    \$\begingroup\$ That's really short! I'll post the outgolfing bounty when the question is old enough to allow it. \$\endgroup\$
    – xnor
    Commented Jul 6, 2023 at 3:54

JavaScript (ES6), 145 bytes

NB: Although I suggested the ASCII art in the sandbox, I didn't make any attempt to compress it until now. I would otherwise have waited before posting this answer.

-1 thanks to emanresu A
-6 by removing trailing spaces, as suggested by l4m2

This is 29 bytes shorter than hardcoding.

227676`.replace(/./g,n=>"( )|"[n>>1]+(n>1?n&1?"__":"  ":n+"_798512630412"[i=-~i]))

Try it online!


The ASCII art is split into 8 distinct patterns of 3 characters:

0: "(0x"    4: ")  "
1: "(1x"    5: ")__"
2: "   "    6: "|  "
3: " __"    7: "|__"

The leading character of the \$n\$-th pattern is picked from the lookup string "( )|" at index \$\lfloor n/2\rfloor\$.

If \$n>1\$, it is followed by either " " (2 spaces) if \$n\$ is even, or "__" if \$n\$ is odd.

If \$n\le1\$, we append \$n\$ as the tens digit and pick the units digit from the lookup string "_798512630412", using the initially undefined argument \$i\$ of the function as a counter.

  • 1
    \$\begingroup\$ -1 byte \$\endgroup\$
    – emanresu A
    Commented Jul 5, 2023 at 10:21
  • 1
    \$\begingroup\$ 2 at ending of line can be omitted? \$\endgroup\$
    – l4m2
    Commented Jul 5, 2023 at 15:48

Python 3, 137 bytes

for k in b"KHLHLHLHKLI	IIHKIIIQKNI\nIQNKNNQQNNKRNNNNNRNKHRNRNRNKHHRNRN":print(end=f"({k:02d}"*(k<13)or" )|\n"[k%4]+" _"[k%3]*2)

Try it online!

Each letter in the hardcoded string corresponds to a triple of characters, of one of " )|\n" followed by two copies of a space or underscore. The unprintable special characters correspond to pin numbers via their ASCII value. They're printed padded to two digits and preceded by an (.

Here's a version without unprintables:

138 bytes

for k in b"KHLHLHLHKLhIjIiIHKfIlImIgQKNdIkIeQNKNNbQcQNNKRNNNNNRNKHRNRNRNKHHRNRN":print(end=k//96*f"({k-97:02d}"or" )|\n"[k%4]+" _"[k%3]*2)

Try it online!

152 bytes

for n in b"	\n\0":
 for c in(n>0)*f"__({n:02})|  ||  ||__|":s[t+t//21*2+k-3//k+k//4*19]=c;k+=1

Try it online!

An alternative method with less hardcoding that turned out longer. Creates the ASCII art by starting with a blank canvas overlaying rectangles like this:

|  |
|  |

with the corresponding pin numbers at the corresponding positions. Thanks to loopy walt for -2 bytes.

  • 1
    \$\begingroup\$ Anything wrong with "%23c"%10*8? \$\endgroup\$
    – loopy walt
    Commented Jul 19, 2023 at 2:06

K (ngn/k), 112 110 bytes

`0:8 22#?[;;]//[176#"";i[<i]+\:5 2#+\"",7#4 18;{("__";x/"()"),"  _"^\:"|  |"}'-2$$w:101+<i:"HN/;(   5\""]

Try it online!

Places the pins top to bottom one after another in an initially empty grid.

Some of the strings contain unprintables that are swallowed by SE markdown. Click on the link to get the full code.


-1B from c--

C (gcc), 150 bytes

i;f(c){for(i=0;c="226262425G5I5H41E5K5L5F031C5J5D30331A1B33037333337023737370223737"[i++];printf(c>64?"%02.f)":c&4?"__%c":"%3c",c-64.,"\n( |"[c%4]));}

Try it online!


Python 3, 164 163 bytes

  • -1 thanks to The Thonnu for the docstring implementation, very neat! I would never have thought to do this.

Very little I tried was shorter than a few substitutions and str repetitions. But, Im horrible at strings in python so please lmk if yall find something. I'm sure theres a better approach in totality and will be checking back on other answer to learn :)

a="  |__|"
print("    __"*3+"""
|  (03)__(10)__(04)  |
|  |  (01)  (02)  |  |
|__"""+"|  "*5+"|__|\n",a*3+"\n   ",a*2)

Try it online!


C (gcc) -funsigned-char, 144* bytes

i;main(c){for(;c=c/16?:"3333:\3033;\2003>\3633   6\3233! A! 3!!!32#2#2#!3!3"[i++];)printf(c&12?"(%02d)":L"\n |_"+c%4,c%16-3);}

Try it online!

There's some unprintable characters in the string, you should be able to see them on TIO.

*: I wasn't able to insert some characters on TIO, you have to encode each octal char in the string as a single byte instead of an escape code. Here's the string and a bash script to build it locally:

Try it locally


#include <stdio.h>
char s[] = {
    0x11, 0x11, 0x33, 0x11, 0x11, 0x33, 0x11, 0x11, 0x33, 0x10,
    0x33, 0x3a, 0xc3, 0x33, 0x3b, 0x03, 0x80, 0x33, 0x3e, 0xf3,
    0x33, 0x09, 0x20, 0x11, 0x36, 0xd3, 0x33, 0x17, 0x21, 0x20,
    0x11, 0x12, 0x41, 0x11, 0x15, 0x21, 0x11, 0x02, 0x20, 0x33,
    0x12, 0x21, 0x11, 0x12, 0x21, 0x11, 0x12, 0x21, 0x33, 0x02,
    0x10, 0x11, 0x32, 0x23, 0x11, 0x32, 0x23, 0x11, 0x32, 0x23,
    0x10, 0x11, 0x11, 0x21, 0x33, 0x12, 0x21, 0x33, 0x02, 0x00,
int main(){fputs(s, stdout);}

bash script:

gcc -o str str.c
cat >molkky.c \
    <(printf %s 'i;main(c){for(;c=c/16?:"') \
    <(./str) \
    <(printf %s '"[i++];)printf(c&12?"(%02d)":L"\n |_"+c%4,c%16-3);}')
# verify size with `wc -c molkky.c`
gcc -w -funsigned-char -o molkky molkky.c

05AB1E, 67 bytes

•1wÕ—VîaÉîñG)ùǝn\ιÏòáð×т}í(¿°ç÷É¡¤©•"_ |a(

Try it online.


Step 1: Generate halve the shape with dummy value for the numbers:

               # Push compressed integer 32061609852501126428829348223954853956247903207401179145663962432977933413421358
"_ |a(\n)"Åв   # Convert it to custom base-"_ |a(\n)", which basically converts it to
               # base-length, and indices each value into this string
            J  # Join this list of characters to a single multiline string

Try just step 1 online.

Step 2: Mirror it to have the full shape:

º              # Horizontally mirror the multiline string

Try the first two steps online.

Step 3: Replace the dummy value with the numbers at the correct positions:

'a            '# Push string "a"
•ëç‰ÊÉ&.åÈž•   # Push compressed integer 1070908051112060310040102
            ¦  # Remove the leading 1
S              # Convert it to a list of digits
 .;            # Replace every first occurrence of "a" in the multiline string one by
               # one with these digits
               # (after which the result is output implicitly)

I've used this 05AB1E tip to generate the code of step 1.
See this 05AB1E tip of mine (section How to compress large integers?) to understand why •1wÕ—VîaÉîñG)ùǝn\ιÏòáð×т}í(¿°ç÷É¡¤©• is 32061609852501126428829348223954853956247903207401179145663962432977933413421358 and •ëç‰ÊÉ&.åÈž• is 1070908051112060310040102.


Bash, 147 bytes

sed 's/A/  /g;s/B/__/g;s/C/|  /g;s/D/)__(/g'<<E

Try it online!

Port of G B's Ruby answer


Ruby, 156 147 bytes

puts"9kkdofqiz475318ru58n0ar9fnhjekvkdkkidk".to_i(36).digits(8).map{|y|"    __)__(%s)  |  |__
"[y*3,3]}.join%("070908051112060310040102".scan /../)

Try it online!

Second lazy attempt


Vyxal, 524 bitsv1, 65.5 bytes


Try it Online!

A simple "encode everything as a magic number and base decompress" approach.



»×3Ḃ≥tPkǔλu₍εc7Ėµz¤ꜝµ]¼εȮẎ-{Cḟȧ7x+¨Ȧ≥yĊ⁋»   # ‎⁡The number 230294082147299956815045524104987124251723716866820093416899236760877183504036402931220223094
                                         `  # ‎⁢Converted to bijective base "<newline> %_|"
      »c;ṅm₴y„»₄τ                           # ‎⁣The list ⟨ 7 | 9 | 8 | 5 | 11 | 12 | 6 | 3 | 10 | 4 | 1 | 2 ⟩
                 vS                         # ‎⁤With each number converted to string
                   2↳                       # ‎⁢⁡Padded to have a leading 0 if only one character
                      øb                    # ‎⁢⁢Each surrounded in ()
                        %                   # ‎⁢⁣Formatted into the bijective base converted string

💎 Created with the help of Luminespire at https://vyxal.github.io/Luminespire

Ruby, 132 bytes

a=(" "*22+$/)*j=9
"!GCC@".bytes{|k|a[m,n=k/16]=("|__|  |(%02d)"%i%=13)[k%8,n];m+=21+n/2}}

Try it online!

Looped version of the below. Explanation to follow.

Ruby, 139 bytes

a=(" "*22+$/)*j=8
a[j+23,4]=a[j+46,4]="|  |"

Try it online!

A full program that creates a canvas of 8 lines of 22 spaces and a newline, modifies it by adding the pins one by one from top to bottom, and then prints it.

The characters in the magic string are in the format (number of characters to advance from the previous pin) * 13 + (value of pin)

It should be possible to golf this quite a bit by drawing each pin line by line from top to bottom using a loop instead of hardcoding each line of the pin.


Python, 130 bytes

for j in b"ouS_7I!-'Y=C"*6:k-=1;j+=k//12%8%6*25;A=A[:j-4]+f" __ |  ||__|({-k:02})"[k//24*4:][:4]+A[j:]

Attempt This Online!


Draws all the pins "simultaneously" line-by-line bottom up so stuff that should be hidden gets overwritten.

Python, 150 bytes

A='';h="|      "
for*c,z in*"_  |_|_","|  ":h='|'+2*z+h[:7];A=(h[:3:-1]+h[:6]+h+"\n"+A).replace(*c or(4*'|',"(%02x)"),14)
print(A%(*b'	',))

Attempt This Online!

Not good enough to compete with the xnors and dingledoopers of this world but I still kind of like it.


Uses the approximate facts that the figure is left-right symmetric and each half's lines can be obtained sequentially by shifting the previous line by three characters (up to a wobble in the centre) to "procedurally" generate the figure. The final number insertion is stolen from dingledooper.


JavaScript (Node.js), 279 bytes

Solution without hardcoding, which was kind of a hell to write.
But i needed to be exactly sure how much longer it was than the output itself!

_=>[...Array(128)].map((_,i)=>(a=i%16)+0*(d=p=>Math.abs(8-a)/2+Math.abs((b=1+i/16|0)-p))(0)?a%2?d(4.5)<=5&b>1?d(2)<=5&b<6?")("[(a/2+b|0)%4%2]:'|':' ':d(2)%4&(d(2)<5&b<5|d(2)==7|i==104)?'__':d(3)<4&b>1&b<6&i!=72?((t=d(2.5)==1.5)?"":"0")+(14-d(3)-b*2+(a+b>11)+t*4):'  ':`

Try it online!

(i'll add some explanations when i'll have more time to get back into this code)


Racket - 404 bytes

I didn't want to hardcode the string (even though it would've made life easier). I spent roughly half of today trying to encode the string BY HAND and came up with this solution. I do believe there is a simpler encoded solution, but I had fun :)

#lang racket
(let([? char=?])(display(string-join(map(λ(c)(cond[(? c #\a)"    "][(? c #\b)"__"][(? c #\c)"\n"][(? c #\d)"__(0"][(? c #\e)")__(0"][(? c #\f)")__\n(0"][(? c #\g)")__(1"][(? c #\h)"|  (0"][(? c #\i)")  |"][(? c #\j)"|  "][(? c #\k)")  (0"][(? c #\l)"  |"][(? c #\m)"__|"][(? c #\n)"\n  "][else(string c)]))(string->list"abababc d7e9e8f5g1g2e6)ch3g0e4icjh1k2ilc|mlllllmn |mlmlmna|mlm"))"")))

Try it online!


We first convert the encoded string into a list via string->list. We pass this to map which passes the encoded character c a lambda function to test whether c matches any defined options. If it does, we return the corresponding string, otherwise we just return c as is. After the map is finished, we join all the results together and display the single string.

(let ([? char=?])
    (map (lambda (c)
           (cond [(? c #\a) "    "]
                 [(? c #\b) "__"]
                 [(? c #\c) "\n"]
                 [(? c #\d) "__(0"]
                 [(? c #\e) ")__(0"]
                 [(? c #\f) ")__\n(0"]
                 [(? c #\g) ")__(1"]
                 [(? c #\h) "|  (0"]
                 [(? c #\i) ")  |"]
                 [(? c #\j) "|  "]
                 [(? c #\k) ")  (0"]
                 [(? c #\l) "  |"]
                 [(? c #\m) "__|"]
                 [(? c #\n) "\n  "]
                 [else (string c)]))
         (string->list "abababc d7e9e8f5g1g2e6)ch3g0e4icjh1k2ilc|mlllllmn |mlmlmna|mlm"))


    __    __    __
|  (03)__(10)__(04)  |
|  |  (01)  (02)  |  |
|__|  |  |  |  |  |__|
   |__|  |__|  |__|
      |__|  |__|

Have an amazing day everyone :)

  • 1
    \$\begingroup\$ Although you spent quite some time on this challenge, i'm glad you enjoyed it :D According to other answers, a simpler solution would be to do the encoding by splitting the string in chunks of 3 characters, if you're interested to dive back into the subject ;) \$\endgroup\$
    – Fhuvi
    Commented Jul 6, 2023 at 9:44

Charcoal, 62 bytes

F⪪”←&∧÷⊘FsK⦃NlE"Φ➙⁺¡﹪!⌕~⎇⸿¤”¶«⸿F⪪ι «M³→¿κ«→↗↑³↙)  ↑³↗(⟦__κ ω__

Try it online! Link is to verbose version of code. Explanation: Corresponds to @xnor's 154-byte Python approach, although I hadn't seen it at the time.


Split the compressed string 07 09 08\n05 11 12 06\n 03 10 04\n 01 02" on newlines and loop over each row.


Start a new row of output.

F⪪ι «

Split the row on spaces and loop over each column.


Move to the next column.


If there is a pin at this position, then...

→↗↑³↙)  ↑³↗(⟦__κ ω__

... draw the pin without moving the cursor.

The cursor actually starts at the cell below the first _ in the bottom row. It moves right and then up and right, then draws three |s up, then draws the ) and two spaces diagonally down and left (the first of these spaces overwrites one of any _ from a previous pin), then draws three |s up again for the left of the pin, the draws the ) up and right, then draws 5 lines of text __, pin number, space, nothing, __, leaving the cursor where it started.


Jelly, 69 bytes

I was expecting this method to result in more terse code than this, oh well...

“'EçS¬aßQ35%C‘d5ṃ⁶Ėç/€»/Y®,“| _”¤y

A full program taking no arguments that prints the ASCII art, or a niladic Link that yields a string including the newline characters.

Try it online!


Creates each pin in the correct location on its own using characters below ( and greater than in an order* such that they may then be merged using » (maximum) and finally translates this string into one with the expected characters.

* Also uses different characters for the _ at the top of a pin and the _ at the bottom of a pin so they merge in a different order.

+ȷṾṫ-Ø(j“Ẓ“m³ṭ’ṃ“#%&$”©¤js4;Ɱ;ƭ@ƒ@ - Link 1: int PinNumber; lists of space characters [R, C]
+ȷ                                 - {PinNumber} add 1000
  Ṿ                                - unevaluate -> list of characters
   ṫ-                              - tail from index -1 -> two characters with the leading zero if need be
     Ø(j                           - "()" joined with {that} -> e.g. PPN = "(07)"
                       ¤           - nilad followed by links as a nilad:
        “Ẓ“m³ṭ’                    - [190, 6908225]
                “#%&$”             - "#%&$"
                      ©            - (copy "#%&$" to the register for later use)
               ṃ                   - base decompress {[190, 6908225]} with digits {"#%&$"}
                                       -> ["%&&%", "#%%##%%##$$#"]
                        j          - join {that} with {PPN}
                         s4        - split into chunks of length four
                                       -> e.g. ["%&&%", "(07)", "#%%#", "#%%#", "#$$#"]
                                ƒ@ - start with {that} and reduce with {[r, c]} applying:
                              ƭ@   -   alternate between these with swapped arguments:
                           ;Ɱ      -     map with concatenate
                             ;     -     concatenate
                                     -> pin made of #%&$ characters at its desired location

“'EçS¬aßQ35%C‘d5ṃ⁶Ėç/€»/Y®,“| _”¤y - Main Link: no arguments
“'EçS¬aßQ35%C‘                     - code page indices = [39,69,23,83,7,97,21,81,51,53,37,67]
              d5                   - div-mod by five -> [[7,4],[13,4],[4,3],[16,3],[1,2],[19,2],[4,1],[16,1],[10,1],[10,3],[7,2],[13,2]]
                ṃ⁶                 - base decompress {that} with digits [space character]
                  Ė                - enumerate -> [[1,["       ", "    "]], [2,...], ...]
                   ç/€             - reduce each using Link 1 as a dyad
                      »/           - reduce by maximum (vectorises)
                        Y          - join with newline characters -> X
                                ¤  - nilad followed by link(s) as a nilad:
                         ®         -   recall "#%&$" from the register
                          ,“| _”   -   pair with "| _"
                                 y - translate {X} with mapping {["#%&$", "| _"]}
                                       N.B. $ translates to _ as well as & as it is out of range
                                   - (if running as a program) implicit print

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.