Draw the Moon Phase

20

1

Challenge

Given the phase of the moon, draw it using ASCII art.

Your program must handle new moon, waxing crescent, first quarter, waxing gibbous, full moon, waning gibbous, last quarter, and waning crescent. Your input will be an integer.

0 -> new moon
1 -> waxing crescent
2 -> first quarter
3 -> waxing gibbous
4 -> full moon
5 -> waning gibbous
6 -> last quarter
7 -> waning crescent

The ASCII art is all placed on a 16x8 grid (because character dimension ratios). You can replace . with any character and # with any other non-whitespace character.

The output for new moon should be:

................
................
................
................
................
................
................
................

For waxing crescent:

..........######
............####
.............###
.............###
.............###
.............###
............####
..........######

For first quarter:

........########
........########
........########
........########
........########
........########
........########
........########

For waxing gibbous:

......##########
....############
...#############
...#############
...#############
...#############
....############
......##########

And for full moon:

################
################
################
################
################
################
################
################

The waning crescent is just the waxing crescent with each line reversed, as with the waning gibbous and the waxing gibbous, and the first and last quarter.

Rules

  • Standard Loopholes Apply
  • You may choose to output waxing/waning in the opposite direction if you want, though it should make no difference (the graphics shown in this question are for the northern hemisphere)
  • Your output must be exactly as specified. Your newlines can be any reasonable line separator, and you may have a trailing newline if you would like.

HyperNeutrino

Posted 2017-05-17T03:37:36.947

Reputation: 26 575

5Relevant xkcd. – Martin Ender – 2017-05-17T05:55:43.500

"though it should make no difference" - saved me a byte (I hope I got it right) :) – Jonathan Allan – 2017-05-17T09:19:01.480

1Does it have to be ASCII art? MoonPhase["Icon"] is 17 bytes in Mathematica… – Not a tree – 2017-05-17T10:27:02.470

@JonathanAllan Oh nice. Well then it might make a difference :P – HyperNeutrino – 2017-05-17T11:33:33.320

@lanlock4 You stated one of the reasons why I made it ASCII art. Also yes it does have to be ASCII art. – HyperNeutrino – 2017-05-17T11:34:13.800

Answers

7

Jelly,  43 32 bytes

-7 bytes moving from bit-mask to comparison-mask
-2 bytes with some tacit programming improvements
-1 byte moving to the southern hemisphere
-1 byte - use the all-new ɓ chain separator ...its first ever use!

“>,##‘m0Dm€0ż@€4Ḷ¤Œṙɓ%4>C¹⁸:4¤?Y

Uses the characters 0 for . and 1 for #.

All cases in a test suite at Try it online!

How?

Builds a mask capturing the first four phases, and rather than reversing the lines complements the resulting values of the modulo-4 phase result when the phase div-4 is non-zero.

I originally built a bit mask, but the mask values were 0,8,12, and 14 - 0000, 1000, 1100, and 1110 - these have phase leading ones - so a comparison-mask could be used instead.

“>,##‘m0Dm€0ż@€4Ḷ¤Œṙɓ%4>C¹⁸:4¤?Y - Main link 1: number phase
“>,##‘                           - code-page index literal [62,44,35,35]
      m0                         - reflect -> [62,44,35,35,35,35,44,62]
        D                        - decimalise -> [[6,2],[4,4],[3,5],[3,5],[3,5],[3,5],[4,4],[6,2]]
         m€0                     - reflect €ach -> [[6,2,2,6],[4,4,4,4],[3,5,5,3],[3,5,5,3],[3,5,5,3],[3,5,5,3],[4,4,4,4],[6,2,2,6]]
                 ¤               - nilad and link(s) as a nilad:
               4                 -   literal 4
                Ḷ                -   lowered range -> [0,1,2,3]
            ż@€                  - zip (reverse @rguments) for €ach -> [[[0,6],[1,2],[2,2],[3,6]],[[0,4],[1,4],[2,4],[3,4]],[[0,3],[1,5],[2,5],[3,3]],[[0,3],[1,5],[2,5],[3,3]],[[0,3],[1,5],[2,5],[3,3]],[[0,3],[1,5],[2,5],[3,3]],[[0,4],[1,4],[2,4],[3,4]],[[0,6],[1,2],[2,2],[3,6]]]
                  Œṙ             - run-length decode -> [[0,0,0,0,0,0,1,1,2,2,3,3,3,3,3,3],[0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3],[0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3],[0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3],[0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3],[0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3],[0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3],[0,0,0,0,0,0,1,1,2,2,3,3,3,3,3,3]]
                                    -   i.e.: 0000001122333333  -
                                              0000111122223333  - Marking out the separate
                                              0001111122222333  - regions as filled up by
                                              0001111122222333  - the phases of the moon in
                                              0001111122222333  - the southern hemisphere.
                                              0001111122222333  -
                                              0000111122223333  -
                                              0000001122333333  -
                    ɓ            - dyadic chain separation & swap arguments, call that m
                     %4          - phase mod 4
                       >         - greater than? (vectorises across m) 1 if so 0 if not
                              ?  - if:
                             ¤   -   nilad followed by link(s) as a nilad:
                          ⁸      -     link's left argument, phase
                           :4    -     integer divide by 4
                        C        - then: complement
                         ¹       - else: identity (do nothing)
                               Y - join with newlines
                                 - implicit print

Jonathan Allan

Posted 2017-05-17T03:37:36.947

Reputation: 67 804

3that's not a language, it's modem noise... – Alnitak – 2017-05-17T16:27:50.690

@Alnitak Welcome to PPCG! Did you join this PPCG.SE just so you could make that comment? ;) – HyperNeutrino – 2017-05-18T01:47:47.100

8

JavaScript (ES6), 121 ... 103 92 bytes

f=(n,i=128)=>i--?f(n,i)+(i%16?'':`
`)+'.#.'[i%16+4*n-~-'31000013'[n&1?i>>4:1]*~-(n&2)>>4]:''

Demo

f=(n,i=128)=>i--?f(n,i)+(i%16?'':`
`)+'.#.'[i%16+4*n-~-'31000013'[n&1?i>>4:1]*~-(n&2)>>4]:''

o.innerHTML=f(0)
<input type="range" oninput="o.innerHTML=f(this.value)" value=0 min=0 max=7><pre id=o>

Arnauld

Posted 2017-05-17T03:37:36.947

Reputation: 111 334

Aw, I wanted to give this a stab at lunchtime. Doubt I would have beaten you, though. – Shaggy – 2017-05-17T09:46:39.867

4

Haskell, 98 90 bytes

f i=do{a<-[3,1,0,0,0,0,1,3];[".#."!!div(i*4+x+[0,a-1,0,1-a]!!mod i 4)16|x<-[0..15]]++"\n"}

It loops through the rows and columns using the list monad (a do block for rows and a list comprehension for columns) and determines which character for each cell using a expression of the input (i), offset value for the row (a), and column index (x).

Saved 8 bytes by simplifying the subexpression for the true offset.

faubi

Posted 2017-05-17T03:37:36.947

Reputation: 2 599

3

Python 2, 144 142 127 bytes

i=input()
a,b='#.'[::i/4*2-1]
i%=4
for x in range(8):y=(int(abs(x-3.5))or 1)+2;y=[y,16-y][i>2];y=[i*4,y][i%2];print(16-y)*a+b*y

Try it online!

Can definitely be golfed further, tips are appreciated :)

Golfed off 1 byte thanks to undergroundmonorail!

Golfed off many bytes thanks to ovi and Mego because I'm a fool who forgets to not use 4 spaces for codegolf :)

musicman523

Posted 2017-05-17T03:37:36.947

Reputation: 4 472

if i>2:y=16-y could be changed to y=[16-y,y][i>2], which is longer, but with liberal use of semicolons would allow your loop to be a one-liner to save several bytes. – Mego – 2017-05-17T21:12:17.560

2

PHP, 105 Bytes

for(;$i++<8;)echo($p=str_pad)($p("",[16,16-$b=_64333346[$i],8,$b][3&$a=$argn],_M[$a/4]),16,M_[$a/4])."
";

Try it online!

Jörg Hülsermann

Posted 2017-05-17T03:37:36.947

Reputation: 13 026

1why not $a/4? The indexing will do the cutting. :) – Titus – 2017-05-18T02:30:18.483

@Titus i have not know it. Thank You – Jörg Hülsermann – 2017-05-18T09:53:31.740

1

Mathematica, 125 bytes

s=Switch;Grid@If[1<#<6,#&,1-#&][s[m=#~Mod~4,0,0,2,1,_,1-{3.4,5}~DiskMatrix~{8,16}]s[m,1,h=Table[Boole[i>8],8,{i,16}],_,1-h]]&

Returns a grid using 1 and 0 instead of . and # respectively.

It works using two masks, one circular one and one half-shaded one, and logically combining them to get the appropriate shapes.

The two masks are made with 1-{3.4,5}~DiskMatrix~{8,16} for the circular one, and Table[Boole[i>8],8,{i,16}] for the half one. The logic is as follows:

output = f(a AND b)

where f, a and b are:

n | f    a  b
--+-----------
0 | NOT  F  ◨ 
1 | NOT  ○  ◧ 
2 | 1    T  ◨
3 | 1    ○  ◨
4 | 1    F  ◨ 
5 | 1    ○  ◧ 
6 | NOT  T  ◨ 
7 | NOT  ○  ◨

The logic is simulated with 1s and 0s by using multiplication for AND and x -> 1-x for NOT.

A bonus (non-ASCII) solution, for 28 bytes: IconData["MoonPhase",#/4-1]&

Not a tree

Posted 2017-05-17T03:37:36.947

Reputation: 3 106