22
\$\begingroup\$

Introduction:

When we think about Ladybugs, we usually think of a red or dark orange bug with black spots. Although this isn't necessary true, since there are also black with red/orange spotted ladybugs, or ladybugs without spots at all, we mainly picture ladybugs something like this Asian Ladybug:

enter image description here

Another thing to note is that the spots on the ladybugs are almost always symmetric. And that is where this challenge comes in.

Challenge:

Given an integer n (>= 0), output the following ASCII-art ladybug one or multiple times, with symmetric spots evenly divided between the two sides, as well as the two or more ladybugs.

Here is the default ladybug layout:

    _V_ 
  /(@I@)\
 /   |   \
|    |    |
 \   |   /
  ''-!-''

If n=0, we output the ladybug above as is.

When n is larger than zero, we either fill in the spaces of the ASCII-art bug with a lowercase o, or replace the | in the center with a capital O. The goal is to make n changes to the 'empty' ladybug(s), while still producing a symmetric output (per ladybug), and outputting as few ladybugs as possible.

So valid outputs for n=1 are:

    _V_ 
  /(@I@)\
 /   O   \
|    |    |
 \   |   /
  ''-!-''

    _V_ 
  /(@I@)\
 /   |   \
|    O    |
 \   |   /
  ''-!-''

    _V_ 
  /(@I@)\
 /   |   \
|    |    |
 \   O   /
  ''-!-''

But this would be invalid:

    _V_ 
  /(@I@)\
 /   |   \
| o  |    |
 \   |   /
  ''-!-''

Valid outputs for n=2 are:

    _V_ 
  /(@I@)\
 /   O   \
|    O    |
 \   |   /
  ''-!-''

    _V_ 
  /(@I@)\
 /   O   \
|    |    |
 \   O   /
  ''-!-''

    _V_ 
  /(@I@)\
 /  o|o  \
|    |    |
 \   |   /
  ''-!-''

    _V_ 
  /(@I@)\
 /   |   \
| o  |  o |
 \   |   /
  ''-!-''

etc. There are a lot of possible outputs.

The first n that isn't possible to fit into a single ladybug anymore is n=24. In which case you'll have to divide it as evenly as possible into two ladybugs (you can choose whether to output them next to each other, or under one another - with optionally one space or one new-line in between them). For example:

    _V_        _V_ 
  /(@I@)\    /(@I@)\
 /o o|o o\  /o o|o o\
|o o | o o||o o | o o|
 \o o|o o/  \o o|o o/
  ''-!-''    ''-!-''

OR:

    _V_ 
  /(@I@)\
 /ooo|ooo\
|    |    |
 \ooo|ooo/
  ''-!-''
    _V_ 
  /(@I@)\
 /ooo|ooo\
|    |    |
 \ooo|ooo/
  ''-!-''

Challenge rules:

  • n will be in the range of 0-1000.
  • You can choose to output to STDOUT, return as String or 2D-char array/list, etc. Your call.
  • Leading new-lines or unnecessary whitespaces aren't allowed. Trailing white-spaces and a single trailing new-line are allowed.
  • As mentioned above, when two or more ladybugs are necessary, you can choose whether to output them next to each other or below each other (or a mix of both..)
  • When two or more ladybugs are printed next to each other, a single optional space in between is allowed. When two or more ladybugs are printed down one another, a single optional new-line in between is allowed.
  • You can choose the layout of the ladybugs at any step during the sequence, as long as they are symmetric and equal to input n.
  • Since the goal is to have n changes AND as few ladybugs as possible, you will start using more than one ladybug when above n=23. The layout of these ladybugs doesn't necessary have to be the same. In fact, this isn't even possible for some inputs, like n=25 or n=50 to name two.
  • In addition, sometimes it isn't possible to evenly split the dots among two or more ladybugs. In that case you'll have to split them as evenly as possible, with at most a difference of 1 between them.

So for n=50, keeping the last two rules in mind, this would be a valid possible output (where the first bug has 16 spots, and the other two have 17):

    _V_        _V_        _V_ 
  /(@I@)\    /(@I@)\    /(@I@)\
 /oooOooo\  /   O   \  /o oOo o\
|ooooOoooo||ooooOoooo||o ooOoo o|
 \   |   /  \oooOooo/  \o oOo o/
  ''-!-''    ''-!-''    ''-!-''

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.
\$\endgroup\$
  • \$\begingroup\$ What do you mean by "as few changes as possible" to the empty ladybug? When placing n (<24) letters o/O onto a single ladybug, you make n changes to it. Or do you mean changes from n-1 to n (so outputs vary by as little as possible when inputs vary by 1)? \$\endgroup\$ – Heimdall Nov 2 '17 at 11:05
  • \$\begingroup\$ @Heimdall Ah sorry for the confusion due to bad wording. This was when I had the idea to allow multiple characters to form one spot when I thought of this challenge, but I dropped this and just used o and O instead. I've changed the wording a bit. \$\endgroup\$ – Kevin Cruijssen Nov 2 '17 at 12:23
  • \$\begingroup\$ For the n=50 example, I believe that you mean the first bug has 16 spots and the other two each have 17. \$\endgroup\$ – Jon Claus Nov 2 '17 at 16:09
  • \$\begingroup\$ This is my favorite Jimi Hendrix album. \$\endgroup\$ – iamnotmaynard Nov 7 '17 at 14:27
  • \$\begingroup\$ @iamnotmaynard Maybe I'm missing something obvious, or did you comment on the wrong challenge? I don't really see the link between Jimi Hendrix and ladybugs.. \$\endgroup\$ – Kevin Cruijssen Nov 7 '17 at 16:08
5
\$\begingroup\$

Charcoal, 84 81 bytes

Nθ≔⌈∕∨θ¹¦²³ηFη«≔⁺÷θη‹ι﹪θηζV_¶I@)↘²↙|/←''-↑!↑⎇›ζ²¹OO²§|OζE037×o⌊⟦⁻÷ζ²Iκ⁺³⁼κ3⟧↙»‖B←

Try it online! Link is to verbose version of code. Explanation:

Nθ

Input the total number of spots.

≔⌈∕∨θ¹¦²³η

Calculate the number of ladybirds needed.

Fη«

Loop over each ladybird.

≔⁺÷θη‹ι﹪θηζ

Calculate the number of spots to put on this ladybird.

V_¶I@)↘²↙|/←''-↑!

Print the head and right wing of the ladybird.

↑⎇›ζ²¹OO²

If there are more than 21 spots, print two spots, otherwise print the back.

§|Oζ

If the number of spots is odd print another spot otherwise print the rest of the back.

E037×o⌊⟦⁻÷ζ²Iκ⁺³⁼κ3⟧

Divide the number of spots by two, and distribute them among three rows of 3, 4, and 3 spots.

↙»

Move to the start of the next ladybird.

‖B←

Reflect the canvas to the left, keeping the back.

\$\endgroup\$
8
\$\begingroup\$

Python 2, 252 249 238 212 211 213 209 bytes

n=input()
x=(n+22)/23or 1
for i in range(x):b=n/x+(n%x>i);c=r"""    _V_
  /(@I@)\
 /361%s163\
|408717804|
 \5201025/
  ''-!-''"""%'|O'[b%2];i=0;exec"c=c.replace(`i%9`,' |oO'[i>9::2][i<b/2],2);i+=1;"*11;print c

Try it online!

  • Saved 9 bytes thanks to Kevin Cruijssen
  • Saved 18 bytes thanks to Mr. Xcoder
  • Saved 2 bytes thanks to Jonathan Frech
\$\endgroup\$
  • \$\begingroup\$ I think you can remove the .replace('A','|O'[b%2]) and use c=" _V_\n /(@I@)\ \n /361"+'|O'[b%2]+"163\ \n|4087B7804|\n \\529B925/\n ''-!-''" instead? \$\endgroup\$ – Kevin Cruijssen Nov 2 '17 at 9:51
  • \$\begingroup\$ 230 bytes by turning [' o','|O'][i>9] into ' |oO'[i>9::2] and using | instead of logical or. Also turning for i in range(11) to an exec statement saved 4 bytes. \$\endgroup\$ – Mr. Xcoder Nov 2 '17 at 12:29
  • 1
    \$\begingroup\$ And sorry for the comment clutter, but 218 bytes by mixing your list comprehension with the for loop, removing an unnecessary variable as well. \$\endgroup\$ – Mr. Xcoder Nov 2 '17 at 12:38
  • \$\begingroup\$ @Mr.Xcoder Thanks a lot :) \$\endgroup\$ – TFeld Nov 2 '17 at 12:46
  • \$\begingroup\$ It's supposed to produce the fewest ladybugs possible, no? When I put in 24 through 46 on TIO, it gives 3 ladybugs instead of two. \$\endgroup\$ – Nick Matteo Nov 2 '17 at 16:57
7
\$\begingroup\$

JavaScript (ES6), 183 186 bytes

Uses the same formula as TFeld's answer to split the spots among the ladybugs.

n=>(g=k=>k--?`    _V_
  /(@I@)\\
 /3\\
|4|
 \\3/
  ''-!-''
`.replace(/\d/g,i=>(h=s=>i--?h((p=N?(N-=2,'o'):' ')+s+p):s)('|O'[N>2*i|N&1&&+!!N--]),N=(n%j>k)+n/j|0)+g(k):'')(j=n/23+.99|0||1)

Demo

let f =

n=>(g=k=>k--?`    _V_
  /(@I@)\\
 /3\\
|4|
 \\3/
  ''-!-''
`.replace(/\d/g,i=>(h=s=>i--?h((p=N?(N-=2,'o'):' ')+s+p):s)('|O'[N>2*i|N&1&&+!!N--]),N=(n%j>k)+n/j|0)+g(k):'')(j=n/23+.99|0||1)

console.log(f(0))
console.log(f(1))
console.log(f(9))
console.log(f(25))

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

Befunge, 292 279 bytes

#j07-00p&>::1-27*9+/\!!*:1+06pv-1_@#:<<g61$<<:
v"h"**95%2:+`g61%g60\/g60::p61<>-0g*+35*-,:!|
>\-30p2/:55+`:59**"g"\-40p-26pv^*84\!`"."::<<9
v\%+55+g62:%+55+4*g62:::-1<+55<>:"/n"$#->#<^#<
>`26g!+"O"*"Y"\-\-\5+0p:>#^_" 66<0<66// >,-"v
"n //>7OXO8k />'&%$%&'k !(*+)#)+*(! /k,-.$."<v

Try it online!

Explanation

The ASCII art for the ladybug is encoded in a single Befunge string, offset by 15, to allow the first 15 printable characters to be reserved for special purposes. The first two of these special characters represent the newline and the | character, both of which would otherwise not be printable. The third isn't used, because it's a ", which can't be used in a string. The next two represent the large spots in the centre. And the remaining ten are for the spots on the wings.

These special characters are translated into their final form via a lookup table, which is written over the first part of the first line.

To make it easier to explain, this is the code with the various component parts highlighted:

Source code with execution paths highlighted

* We start by initialising the newline and | character in the lookup table, since these are constant.
* Next we read in the number of spots from stdin and calculate the number of ladybugs required.
* We can then start the outer loop for the set of bugs, calculating the number of spots for the next ladybug to be rendered.
* For each ladybug, we calculate whether the large centre spot needs to be shown (if spots%2 == 1), and write the appropriate value into the lookup table.
* Similarly, we calculate whether the other pair of large spots need to be shown (if spots/2 > 10), again updating the lookup table. We also calculate the remaining spots required on each wing.
* The final part of the lookup table initialization is a loop that calculates which of the small spots need to be displayed. Essentially the algorithm is: if (spotnum*spotcount+4)%10 > ((spotnum+1)*spotcount+4)%10, then the spot needs to be displayed.
* Next we push the encoded string representation of the ladybug onto the stack. This is essentially just a simple string, but it became a bit convoluted as I tried to squeeze it into the gaps in the code so the source would form a rectangle.
* At this point, we're ready to begin the output loop, processing the characters one by one, converting the special cases (the spots, line breaks, etc.) via the previously constructed lookup table.
* Finally we check whether we've displayed all the required ladybugs, otherwise continue back to the start the of the outer loop.

\$\endgroup\$
  • \$\begingroup\$ Nice, I really like the patterns your ladybugs have for each stage from 1-23. Quite different than some of the other answers. +1 from me. Would you mind adding an explanation (after you're perhaps done golfing it further)? \$\endgroup\$ – Kevin Cruijssen Nov 5 '17 at 11:25
  • 1
    \$\begingroup\$ I'm glad you liked the patterns. I actually spent quite a lot of time trying out the different combinations to find an algorithm that looked good in as many of the stages as possible. Also added a bit of an explanation to my answer now. \$\endgroup\$ – James Holderness Nov 6 '17 at 0:44
3
\$\begingroup\$

Ruby, 203 193 190 bytes

f=->n{s=%q{    _V_ 
  /(@I@)\
 /137x731\
|0596x6950|
 \248x842/
  ''-!-''
}
n-=d=n>0?n/(1+~-n/23):0
s.gsub!(/\d/){$&.to_i<d/2??o:' '}
x=[d%2,d<=>21]*2
s.gsub!(?x){"|O|"[x.pop]}
n>0?s+f[n]:s}

Try it online!

  • Saved 10 bytes thanks to Jordan
\$\endgroup\$
  • \$\begingroup\$ {|m|m. can be replaced with {$&.; b=(n-1)/23+1 can be replaced with b=1+~-n/23; and x=[z=d>21,d%2>0,z]⏎s.gsub!(?x){x.pop ? ?O:?|} can be replaced with x=[d%2,d<=>21]*2⏎s.gsub!(?x){"|O|"[x.pop]}. \$\endgroup\$ – Jordan Nov 6 '17 at 22:10
  • \$\begingroup\$ You can save another byte by using %q{XY} instead of 'X'+"Y" on the first eight lines and a couple more by doing d=n>0?n/(b=1+~-n/23):b=0 instead of n>0?d=n/(b=(n-1)/23+1):d=b=0. \$\endgroup\$ – Jordan Nov 6 '17 at 22:17
  • \$\begingroup\$ @Jordan Wow, thank you. \$\endgroup\$ – iamnotmaynard Nov 8 '17 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.