【javascript】演算子なしでFizzBuzzを書く
※この記事には通常では考えられないような記法が多々登場します
演算子、使ってますよね?ね??(こんな記事見てる人なら)
Javascriptにはたくさんの演算子があります。
それを使わないチャレンジです。要は自慢したいだけ
演算子の規定
演算子の規定は基本的にMDN Web Docsの式と演算子のページを参照しました
主なものは下記のものです(これが全てではないです)
算術演算子:+
-
*
/
%
**
比較演算子:==
!=
<
>
代入演算子:=
論理演算子:!
&&
||
三項演算子:? :
グループ化:()
そしてプロパティアクセス演算子です
プロパティアクセス演算子
あまり聞き馴染みのない演算子ですが察しの良い方はもうお気づきでしょう
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
console.log()
console["log"]()
そうですこいつらです。
チェーン記法とブラケット記法です。
最後まで閲覧していただき、ありがとうございます
追記: 「プロパティアクセスは演算子ではないのでは」と指摘されましたが、規定で書いてしまったものは仕方がないので、
試し書き
まず一旦FizzBuzzを書いてみる
for(let i = 0; i <= 100; i++) {
if(!(i % 15)) {
console.log('FizzBuzz');
} else if(!(i % 5)) {
console.log('Buzz');
} else if(!(i % 3)) {
console.log('Fizz');
} else {
console.log(i);
}
}
問題点
- チェーン表記が使えない
- 割り算ができない
- 代入やインクリメントができない(forが使えない)
- 正誤判定ができない
デバッグ
チェーン表記
一番問題なのがconsole.log()
が禁止であるということ
どうしよ諦めよっかな、、、
そういえばwith
句ある!※非推奨
with句とは
ざっくり言うと()
の中の要素を{}
内で展開する、、みたいな?
with(console) {
log('Fizz');
error('Buzz');
}
こんな感じ。
とりあえず一番問題だったチェーン表記ができない問題はなんとかなった。
繰り返し
が、 それがかけたとて繰り返しがなぁ、、、
再帰使うか!
function main(i) {
/* 処理 */
main(i + 1)
}
インクリメントできねぇな、、、
どうしよ
[1,2,3,...,99,100]
でfor-of
使うとかいけないかな
配列のfor-in
配列番号返した気がする?
おお、返した!
for(i in ['a','b']) {
/* 処理 */
}
OKこれで100回繰り返す処理は書けた
for(i in Array(100)) {
/* 処理 */
}
あれ、動かない、、
どうやら配列内の中身がないと動かないらしい
なら文字化してみる。(2マスのスペースは文字数追加分)
for(i in `${Array(100)} `) {
/* 処理 */
}
出来た!
剰余
なら次は、、剰余?
Mathの中にも良いのないしなぁ、、、
n進法の一の位で行ける!
なら
Number(i.toString(x).at(-1))
をwith
句で書いて
with(i) {
with(toString(x)) {
Number(at(-1))
}
}
-1
まさかの-1
が書けないという事態
-1
を返してくれる関数、、
indexOf()
とかだけどまたwith
句、使わないといけないのか、、、
上にstring
が入ってるwith
句があった!
じゃあ
with(i) {
with(toString(x)) {
Number(at(indexOf))
}
}
falsyの判定
あとは0の判定は
if(/* 余り */) {} else {
/* 処理 */
}
で行けるね!
動作確認
for(i in`${Array(100)} `) {
function mod(x) {
with(i) {
with(toString(x)) {
return Number(at(indexOf()))
}
}
}
console.log(mod(15))
}
//=> 0 1 2 3 4 5 6 7 8 9 0 1 ...
おかしい、
n進数に変換できていない?
あ、i
がstr
型だからか。
for(i in`${Array(100)} `) {
function mod(x) {
with(i) {
with(toString(x)) {
return Number(at(indexOf()))
}
}
}
console.log(mod(15))
}
//=> 0 1 2 3 4 5 6 7 8 9 NaN NaN ...
これじゃあNaN
までfalsy
だな、、
(parseInt(at(indexOf()), x)
にして治しました)
0の判定
0で正誤判定するか、、
どうしよ、、、
switch
って等号じゃん!
でもいっぱい書かないといけないのだるいな、、
switch(0)
で判定すればいいか!
for(i in`${Array(100)} `) {
function mod(x) {
with(Number(i)) {
with(toString(x)) {
return parseInt(at(indexOf()), x)
}
}
}
with(console) {
switch(0) {
case mod(15):log('Fizzbuzz');
break;
case mod(5):log('Buzz');
break;
case mod(3):log('Fizz');
break;
default:log(i)
}
}
}
// FizzBuzz 1 2 Fizz 4 Buzz ...
最初の0
だけ飛ばさないといけないけど
switch
文で0
判定がちょうどできるから、、
完成
for(i in`${Array(100)} `) {
function mod(x) {
with(Number(i)) {
with(toString(x)) {
return parseInt(at(indexOf()), x)
}
}
}
with(console) {
switch(0) {
case Number(i):break
case mod(15):log('Fizzbuzz');
break;
case mod(5):log('Buzz');
break;
case mod(3):log('Fizz');
break;
default:log(i)
}
}
}
最後のやつ
最後まで閲覧していただきありがとうございます!
ブログなんて初めて書いたので(にしては内容がおかしい)
拙い部分もたくさんあると思いますが、そこは大目に見ていただいて、、、
for-in
のin
は演算子ではなく式の一部だっていうどうでもいい知識を得ることができました(笑)
使用を見返すいい機会にはなるんじゃないでしょうか?
[is間違った知識] || [hasもっと良い表現] || [esolang好きの変人] ? コメント() : history.go(-1)
そういえば、周りにesolangとかやっている人がいなさ過ぎて困ってます
おまけ
pythonでも書いてみた
def candiv(x, y):
for i, v in enumerate(divmod(x, y)):
if i:
if v:
return 0
return 1
for i in range(1, 101):
if candiv(i, 15):
print("FizzBuzz")
elif candiv(i, 3):
print("Fizz")
elif candiv(i, 5):
print("Buzz")
else:
print(i)