1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iotaでコンパイル時fizzbuzz

Posted at

コード

package main

import (
	"fmt"
)

const (
	sp = 8203
)

const (
	_ = string(sp-8101*(((iota+2)%3)>>1)) +
		string(sp-8098*(((iota+2)%3)>>1)) +
		string(sp-8081*(((iota+2)%3)>>1)) +
		string(sp-8081*(((iota+2)%3)>>1)) +
		string(sp-8105*(((iota+4)%5)>>2)) +
		string(sp-8086*(((iota+4)%5)>>2)) +
		string(sp-8081*(((iota+4)%5)>>2)) +
		string(sp-8081*(((iota+4)%5)>>2)) +
		string(sp-(8155-(iota/10%10))*(1-((((iota+2)%3)>>1)|(((iota+4)%5)>>2)|-((iota-10)>>65535)))) +
		string(sp-(8155-(iota%10))*(1-((((iota+2)%3)>>1)|(((iota+4)%5)>>2))))
	_1
	_2
	_3
	_4
	_5
	_6
	_7
	_8
	_9
	_10
	_11
	_12
	_13
	_14
	_15
)

func main() {
	fmt.Println(_1)
	fmt.Println(_2)
	fmt.Println(_3)
	fmt.Println(_4)
	fmt.Println(_5)
	fmt.Println(_6)
	fmt.Println(_7)
	fmt.Println(_8)
	fmt.Println(_9)
	fmt.Println(_10)
	fmt.Println(_11)
	fmt.Println(_12)
	fmt.Println(_13)
	fmt.Println(_14)
	fmt.Println(_15)
}
1
2
fizz​​​​​​
4
buzz​​
fizz​​​​​​
7
8
fizz​​​​​​
buzz​​
11
fizz​​​​​​
13
14
fizzbuzz​​

しくみ

iotaとコンパイル時計算

iotaはenumとしてよく使われますが、Hoge = iota だけでなく式の形でも宣言できます(数列のように扱えます)。

Effective Go - The Go Programming Language

また、intからstringの型変換もコンパイル時計算可能なため、string(i)でunicodeの文字コードiの文字列を取得可能です。

fmt.Println(string(65)) // A

あとは、iotaの余りに応じてfizzbuzzの文字列に変換すればOKです。

ゼロ幅スペース

しかし、string(i)の方法には1つ欠点があります。なにかしらの文字が常に出力され、文字を表示しないことができないのです。

そこで、目には見えない文字「ゼロ幅スペース」を使用します。

​ - ゼロ幅スペース: U+200B - Unicode キャラクター図鑑

デフォルトでは各文字がゼロ幅スペース(sp)になるようにし、条件を満たすときのみ別の文字列に変更しています。

_ = string(sp-8101*(((iota+2)%3)>>1)) + // "f"(3で割れる) or ""
		string(sp-8098*(((iota+2)%3)>>1)) + // "i"(3で割れる) or ""
		string(sp-8081*(((iota+2)%3)>>1)) + // "z"(3で割れる) or ""
		string(sp-8081*(((iota+2)%3)>>1)) + // "z"(3で割れる) or ""
		string(sp-8105*(((iota+4)%5)>>2)) + // "b"(5で割れる) or ""
		string(sp-8086*(((iota+4)%5)>>2)) + // "u"(5で割れる) or ""
		string(sp-8081*(((iota+4)%5)>>2)) + // "z"(5で割れる) or ""
		string(sp-8081*(((iota+4)%5)>>2)) + // "z"(5で割れる) or ""
		string(sp-(8155-(iota/10%10))*(1-((((iota+2)%3)>>1)|(((iota+4)%5)>>2)|-((iota-10)>>65535)))) + // iotaの10の位(3でも5でも割れず、iotaが10以上) or ""
		string(sp-(8155-(iota%10))*(1-((((iota+2)%3)>>1)|(((iota+4)%5)>>2)))) // iotaの1の位(3でも5でも割れない) or ""

コメントを書くと冗長なのが丸わかりですね... :sweat_smile:

  • 3項演算子が無い
  • boolをintとして使えない
  • 関数が使えない(実行時計算になる)

という縛りがあったので、ビット演算のべた書きになっています。「もっといい方法があるよ!」という方は、ぜひコメント欄に書いていただけるとありがたいです!

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?