Once I could not go to sleep final evening 1 my sleep-deprived mind all of a sudden went “I wager you’ll be able to’t write a Makefile
for FizzBuzz.” Whereas I clearly ought to have responded with Homer Simpson’s basic “Shut up, mind, or I am going to stab you with a Q-tip.”, it was too late, I had already nerd sniped myself. I totally anticipated to waste approach an excessive amount of time on this nevertheless it solely (?) took slightly over an hour to provide you with an answer.
The Makefile
With out additional ado, here is the factor that ought to most likely by no means have occurred:
START := 1
END := 15
NUMS := $(shell seq $(START) $(END))
fizzbuzz: $(NUMS)
mod = $(shell echo $$(( $1 % $2 )))
outline fb
$1:
ifeq "$(name mod, $1, 15)" '0'
@echo FizzBuzz
else ifeq "$(name mod, $1, 3)" '0'
@echo Fizz
else ifeq "$(name mod, $1, 5)" '0'
@echo Buzz
else
@echo $1
endif
endef
$(foreach _,${NUMS},$(eval $(name fb,$_)))
.PHONY: fizzbuzz $(NUMS)
Let’s examine it in motion:
$ make fizzbuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
Since fizzbuzz
is the primary goal we are able to depart it off. And we are able to additionally override START
and END
from the command line:
$ make START=19 END=30
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
Walkthrough
So how does this work? We begin by defining a bunch of variables for the beginning and finish values of the quantity vary we need to examine:
START := 1
END := 15
Subsequent we use the shell
perform to assemble a sequence of numbers with seq
, so NUMS
will include 1 2 3 [...] 14 15
.
Now we are able to arrange a fizzbuzz
goal and record all of the numbers in NUM
as stipulations:
fizzbuzz: $(NUMS)
Subsequent up, slightly helper perform for modulo, since make
itself does not assist arithmetic operations. This makes use of the shell’s arithmetic enlargement mechanism and doesn’t depend on exterior packages like bc
.
mod = $(shell echo $$(( $1 % $2 )))
Now for the enjoyable half 🙂 First, we use outline
to, properly, outline a sequence of make
expressions that we’ll later eval
to show them into targets:
outline fb
$1:
ifeq "$(name mod, $1, 15)" '0'
@echo FizzBuzz
else ifeq "$(name mod, $1, 3)" '0'
@echo Fizz
else ifeq "$(name mod, $1, 5)" '0'
@echo Buzz
else
@echo $1
endif
endef
The code ought to be comparatively easy: we confer with this block of assertion as fb
when calling it and $1
will obtain the worth of the primary argument. Then we do a few ifeq
checks 2
Now we are able to use foreach
together with eval
and name
to outline targets for all the person numbers:
$(foreach _, ${NUMS}, $(eval $(name fb, $_)))
Final however not least, let’s declare all targets as phony to point that they do not associated to actual information.
Abstract
Whereas I most likely want higher hobbies, this was a enjoyable solution to kill a while and I undoubtedly realized a bit extra about make
at the moment. When a pal (hello, Joe 👋) requested me why I did this, my reply was clear: “As a result of I might.” Hack on everybody and do not forget to have enjoyable with expertise!