Skip to content

Instantly share code, notes, and snippets.

@butackle
Last active May 18, 2017 15:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save butackle/56d7736e08ca7011d75d7025cf425d58 to your computer and use it in GitHub Desktop.
Save butackle/56d7736e08ca7011d75d7025cf425d58 to your computer and use it in GitHub Desktop.
逆FizzBuzz
// 一行
((FizzBuzzArr = ["Fizz", "Buzz", "FizzBuzz"], digit = 3) =>[...Array(digit)].reduce((pV, cV, n) =>[...pV,...Array(FizzBuzzArr.length ** n + 1).fill([...Array(n + 1)]).map((arr, index) =>arr.map((v, i) =>FizzBuzzArr[parseInt(index / FizzBuzzArr.length ** i) % FizzBuzzArr.length]))],[]).map((fizzbuzz) =>Object.assign({fizzbuzz,answer: ((target = [...Array((fizzbuzz.filter((fb) => fb === FizzBuzzArr[2]).length + 1) * 15)] .map((v, i) => !((i + 1) % 15) ? FizzBuzzArr[2] : !((i + 1) % 5) ? FizzBuzzArr[1] : !((i + 1) % 3) ? FizzBuzzArr[0] : "" ) .map((v, i, a) => v !== fizzbuzz[0] ? [] : a.slice(i).reduce((arr, v) => arr.filter((v) => !!v).join("/") === fizzbuzz.join("/") ? arr : [...arr, v], [] ) ) .map((arr, index) => arr.filter((v) => !!v).join("/").indexOf(fizzbuzz.join("/")) === 0 && arr.filter((v) => !!v).every((v, i) => v === fizzbuzz[i]) ? arr.map((v, i) => i + index + 1) : false )) =>target.some((v) => !!v) ?target.filter((v) => !!v).reduce((pArr, cArr) => !pArr || pArr.length > cArr.length ? cArr : pArr, false) : []).call()}))).call().map(({fizzbuzz, answer}) =>Object.assign({fizzbuzz: `List: ${ fizzbuzz.join(",") }`,answer: `answer: ${ answer.join(",") }`})).forEach(({fizzbuzz, answer}, i, a) =>console.log(`${ fizzbuzz }${ " ".repeat(a.reduce((len, {fizzbuzz}) => fizzbuzz.length > len ? fizzbuzz.length : len, 0) + 2 - fizzbuzz.length) }${ answer }`))
// 解説
(
// FizzBuzzの組み合わせを作成する
// digit = 組み合わせの長さのリミット
(FizzBuzzArr = ["Fizz", "Buzz", "FizzBuzz"], digit = 3) =>
[...Array(digit)].reduce((pV, cV, n) =>
[
...pV,
// 組み合わせの長さがn+1のFizzBuzzの配列を作成する。組み合わせ数は3のn+1乗
...Array(FizzBuzzArr.length ** n + 1)
.fill([...Array(n + 1)])
.map((arr, index) =>
arr.map((v, i) =>
FizzBuzzArr[parseInt(index / FizzBuzzArr.length ** i) % FizzBuzzArr.length]
)
)
],
[]
)
// 数列を求める
.map((fizzbuzz) =>
Object.assign(
{
fizzbuzz,
answer: (
(target =
// FizzBuzzの配列を作成する。長さは(検索配列内の"FizzBuzz"の数+1)×15
[...Array((fizzbuzz.filter((fb) => fb === FizzBuzzArr[2]).length + 1) * 15)]
.map((v, i) =>
!((i + 1) % 15) ? FizzBuzzArr[2] : !((i + 1) % 5) ? FizzBuzzArr[1] : !((i + 1) % 3) ? FizzBuzzArr[0] : ""
)
// FizzBuzzの配列の中でfizzBuzzと同じ並びになる可能性のあるFizzBuzzの配列の候補を作成する
.map((v, i, a) =>
v !== fizzbuzz[0] ? [] :
a.slice(i).reduce((arr, v) =>
arr.filter((v) => !!v).join("/") === fizzbuzz.join("/") ? arr : [...arr, v], []
)
)
// 上記の配列よりfizzbuzzの条件に合致しているものを選別し、数列に直す。合致していないものはfalseにする。
.map((arr, index) =>
arr.filter((v) => !!v).join("/").indexOf(fizzbuzz.join("/")) === 0 &&
arr.filter((v) => !!v).every((v, i) => v === fizzbuzz[i]) ?
arr.map((v, i) => i + index + 1) : false
)) =>
// 合致している数列の中で、一番少ない長さの配列を選ぶ。条件に合うものが無かった場合には空配列を返す
target.some((v) => !!v) ?
target.filter((v) => !!v).reduce(
(pArr, cArr) => !pArr || pArr.length > cArr.length ? cArr : pArr, false
) : []
).call()
}
)
)
).call()
// 答えを表示させる
.map(({fizzbuzz, answer}) =>
Object.assign({
fizzbuzz: `List: ${ fizzbuzz.join(",") }`,
answer: `answer: ${ answer.join(",") }`
})
).forEach(({fizzbuzz, answer}, i, a) =>
console.log(`${ fizzbuzz }${ " ".repeat(a.reduce((len, {fizzbuzz}) => fizzbuzz.length > len ? fizzbuzz.length : len, 0) + 2 - fizzbuzz.length) }${ answer }`)
)
/**
*
* ["Fizz", "Buzz", "FizzBuzz"]の中から
* 2つの要素を抽出し出来る組み合わせを
* 全て出すことを考えてみる
*
* ↓
*
* [ "Fizz", "Buzz" ]
* [ "Buzz", "FizzBuzz"]
* ・・・・
*/
// 並べる数
const digit = 2;
// 候補配列
const FizzBuzzArr = ["Fizz", "Buzz", "FizzBuzz"];
/**
*
* 組み合わせ図
* Fizz -> 0, Buzz -> 1, FizzBuzz -> 2とした場合
*
*   / 0 0 , 0
* 0 - 1 0 , 1
* \ 2 0 , 2
* 
*   / 0 1 , 0
* 1 - 1 ---> 1 , 1
* \ 2 1 , 2
* 
*   / 0 2 , 0
* 2 - 1 2 , 1
* \ 2 2 , 2
*
*
* 組み合わせ数は候補配列の長さ ** 並べる数 なので 今回は 3 ** 2 = 9通り
* */
/**
* 商・剰余の特性を利用する
*
* 商・・・割り算したときの答え
* 剰余・・割り算したときに割り切れなかった余り
*
* 例、
* 2 ÷ 3 = 商: 0 余り: 2
* 5 ÷ 3 = 商: 1 余り: 2
*
*/
const mod = [];
for (i=0; i<9; ++i){
// 商は割った数の周期で数値が上がっていく
// console.log(`商 -- ${ i }/1: ${ parseInt( i / 1 )} ${ i }/3: ${ parseInt(i / 3 ) }`)
}
//console.log("===")
for (i=0; i<9; ++i){
// 剰余は割った数の周期で循環する
// console.log(`剰余 -- ${ i }%1: ${ parseInt( i / 1 ) % 3} ${ i }%3: ${ parseInt( i / 3 ) % 3 }`)
}
// ↓ この方式を当てはめると、こういう配列が取得できる
// 組み合わせ総数 = 候補数 ** 並べる数
const array = Array(FizzBuzzArr.length ** digit)
// 並べる数の配列を格納
.fill([...Array(digit)])
// 組み合わせを作る
.map((arr, index) =>
arr.map((v, i) =>
parseInt(index / FizzBuzzArr.length ** i) % FizzBuzzArr.length
)
)
;
//
console.log(array);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment