CHUNITHMの"チルノのパーフェクトさんすう教室 ⑨周年バージョン"でスコア999,999を出したい!
2017-12-09
こんにちは!
みやりんです。
今日は1、2、⑨の日!つまりチルノのパーフェクトさんすう教室の日です!チルパはなんと今年⑨周年!おめでとうございます!
9周年を記念して「チルノのパーフェクトさんすう教室 ⑨周年バージョン」が本家IOSYS様より発表されました!
https://youtu.be/9iI0-OdRzHI
この⑨周年バージョンはSEGAの音ゲーCHUNITHMにも収録されることになり、人気を博しているようです。
ところで、人はなぜかくもゾロ目を好むのでしょう。⑨周年バージョンといわれたら9のゾロ目のスコアを目指したくなるのが人間の性というものであります。
というわけで本日のタイトルは、
CHUNITHMの"チルノのパーフェクトさんすう教室 ⑨周年バージョン"でスコア999,999を出したい!
でございます。
さて、まずこれを成し遂げるためにはCHUNITHMのスコアのシステムを知らないとなぁ。とはいっても難しくはありません。
CHUNITHMの基準スコアは1,000,000点です。これを楽曲のノーツ数で割ったものが、ノーツ1つあたりの得点になります。(1つなのにnotesとはこれいかに)
また"JUSTICE CRITICAL","JUSTICE","ATTACK","MISS"の4種類の判定があり、それぞれ1ノーツあたりの得点の、
"JUSTICE CRITICAL" 101%
"JUSTICE" 100%
"ATTACK" 50%
"MISS" 0%
がもらえます。
それぞれの判定の数をC,J,A,M、ノーツ数をNとすれば、最終的なスコアは
(1.01*C+1*J+0.5A+0*M)*(1000000/N)
で求められることになります(小数点以下切り捨て)。
いわゆる理論値は1,010,000点ということになります。
"チルノのパーフェクトさんすう教室 ⑨周年バージョン"のノーツ数はN=1499なので、スコア999,999を出すためには、
999999<=(1.01*C+1*J+0.5A+0*M)*(1000000/1499)<1000000 ⑴
C+J+A+M=1499 ⑵
この連立不等式を満たす非負整数C,J,A,Mを求めればよい、ということになります。
しかしこの連立不等式、パラメータが4つもありとても扱いづらいですね。なんとかならないでしょうか。
まず目につくのは、⑴で係数が0のMですね。これは⑴式から消去できます。
また、1*J+0.5Aの部分は、0.5(2*J+A)と変形できるので、2*J+Aを改めてWとでも置いてみましょう。
すると⑴式は
999999<=(1.01*C+0.5W)*(1000000/1499)<1000000 ⑴'
と変形できます。
パラメータが2つになり簡単になりましたね。
あとは⑴'を満たす非負整数C,Wを総当りで探せばいいでしょう。
⑵式から、0<=C<=1499のCに対して、
W=2*J+A<=2(J+A)=2(1499-C-M)<=2(1499-C)
ですから、Wは0<=W<=2(1499-C)の範囲で探索すればいいことになります。
これを手計算でやるのは骨が折れるので、適当にC言語のプログラムを書くことにします。
はい、こちらが出来上がったプログラムになります!(3分クッキング風)
さて、これを用いてスコア999,999を出すために必要なC,Wを求めてみよう!
ポチッとな!
"解なし"
知ってた。
不定方程式
(1.01C+0.5W)*(1000000/1499)=1000000 ⑶
にはC=0,W=2998という整数解が存在します。
C,Wを整数とすれば、(1.01C+0.5W)の部分は、最小でも0.01単位でしか動かすことができません。1000000/1499>667なので、(1.01C+0.5W)*(1000000/1499)は最小でも6.67単位でしか動かせません。
つまり、⑶に整数解が存在する時点で、⑴'を満たす非負整数C,Wが存在しないことは容易に予想できるのです。
(これは、10,000ノーツ以上ある曲ではスコア999,999を出せるとも解釈できます。今の所そんな曲はありませんが)
どうしよう…このままじゃ企画倒れだなぁ
…
⑨でしょ?まるきゅうでしょ?0が入ってもいいよね…!
0が一個入った999990,999909,999099,990999,909999について先ほどのプログラムで調べてみると…
999099に解があるらしい!
でもこのスコア、自分のハイスコアに近くて出すこと自体が少し難しい。
出せないものはしょうがないのでさらに妥協して0を二個入れることにすると、909099に解が見つかった。
これなら行ける!
解の1つはC=1274,W=152であり、これを目指すことにしよう。
意気揚々とゲーセンに行きやってみたが…
全然できない。C=1274はまだしも、W=152がとても難しい。JUSTICE CRITICAL、JUSTICE、ATTACKの3つのパラメータを管理しなければならないのはとても厳しい。(MISSはスコアに関係ないしほっとけば出るので無視)
どうすっかな、、、
ここで私はあるスキルに目をつけた。(スキルとは、CHUNITHMの要素のひとつである「マップ」を進めるために必要な「ゲージ」を溜める時に、様々な効果をもたらすものです)
その名も"アタックブレイク"。これはATTACKの判定がMISSになるというもので、必然的にA=0とすることができる。
こうすれば、管理するパラメータはJUSTICE CRITICALとJUSTICEの2つとなり、出しやすくなるはず!
目標値はC=1174,J=177,A=0,M=148に設定。
3クレほど回してみた。さっきよりはやりやすいけど、数値の調整はやはりむずかしいね。狙ってJUSTICEを出すのがとても難しい。たまたま嵌るのを待つしかない気がしてきた。
ここまでの文章を書いたのが12月頭だったのだが…結局今日に至るまで出せていないんだよなぁ。いつか出せたら私のTwitter(@maiyaline)で報告しますね。
ではでは〜
使ったプログラムのソースコード(解さえ求まれば良いのでガバガバなんだな)
#include<stdio.h>
int get_notes()
{
int notes;
printf("Please input notes.\n");
scanf("%d",¬es);/*楽曲のノーツ数を取得*/
return(notes);
}
int get_score()
{
int score;
printf("Please input score.\n");
scanf("%d",&score);/*目標スコアを取得*/
return(score);
}
int search(int notes,int score)
{
double piece;
double value;
int i = 0;
piece = 1000000.0/notes;/*1ノーツあたりの点数を計算*/
for(int c = 0;c <= notes;c++)
{
for(int w = 0;w <= 2 * (notes - c);w++)
{
value = piece * (1.01 * c + 0.5 * w);/*対応するスコアを計算*/
if((score <= value) && (value < score + 1))
{
printf("%d,%d\n",c,w);/*目標スコアと一致すれば出力*/
i = i + 1;/*解の個数をカウント*/
}
}
}
if(i == 0)
{
printf("解なし\n");
}
return 0;
}
int main(void)
{
int notes;
int score;
notes = get_notes();
score = get_score();
search(notes,score);
return 0;
}
みやりんです。
今日は1、2、⑨の日!つまりチルノのパーフェクトさんすう教室の日です!チルパはなんと今年⑨周年!おめでとうございます!
9周年を記念して「チルノのパーフェクトさんすう教室 ⑨周年バージョン」が本家IOSYS様より発表されました!
https://youtu.be/9iI0-OdRzHI
この⑨周年バージョンはSEGAの音ゲーCHUNITHMにも収録されることになり、人気を博しているようです。
ところで、人はなぜかくもゾロ目を好むのでしょう。⑨周年バージョンといわれたら9のゾロ目のスコアを目指したくなるのが人間の性というものであります。
というわけで本日のタイトルは、
CHUNITHMの"チルノのパーフェクトさんすう教室 ⑨周年バージョン"でスコア999,999を出したい!
でございます。
さて、まずこれを成し遂げるためにはCHUNITHMのスコアのシステムを知らないとなぁ。とはいっても難しくはありません。
CHUNITHMの基準スコアは1,000,000点です。これを楽曲のノーツ数で割ったものが、ノーツ1つあたりの得点になります。(1つなのにnotesとはこれいかに)
また"JUSTICE CRITICAL","JUSTICE","ATTACK","MISS"の4種類の判定があり、それぞれ1ノーツあたりの得点の、
"JUSTICE CRITICAL" 101%
"JUSTICE" 100%
"ATTACK" 50%
"MISS" 0%
がもらえます。
それぞれの判定の数をC,J,A,M、ノーツ数をNとすれば、最終的なスコアは
(1.01*C+1*J+0.5A+0*M)*(1000000/N)
で求められることになります(小数点以下切り捨て)。
いわゆる理論値は1,010,000点ということになります。
"チルノのパーフェクトさんすう教室 ⑨周年バージョン"のノーツ数はN=1499なので、スコア999,999を出すためには、
999999<=(1.01*C+1*J+0.5A+0*M)*(1000000/1499)<1000000 ⑴
C+J+A+M=1499 ⑵
この連立不等式を満たす非負整数C,J,A,Mを求めればよい、ということになります。
しかしこの連立不等式、パラメータが4つもありとても扱いづらいですね。なんとかならないでしょうか。
まず目につくのは、⑴で係数が0のMですね。これは⑴式から消去できます。
また、1*J+0.5Aの部分は、0.5(2*J+A)と変形できるので、2*J+Aを改めてWとでも置いてみましょう。
すると⑴式は
999999<=(1.01*C+0.5W)*(1000000/1499)<1000000 ⑴'
と変形できます。
パラメータが2つになり簡単になりましたね。
あとは⑴'を満たす非負整数C,Wを総当りで探せばいいでしょう。
⑵式から、0<=C<=1499のCに対して、
W=2*J+A<=2(J+A)=2(1499-C-M)<=2(1499-C)
ですから、Wは0<=W<=2(1499-C)の範囲で探索すればいいことになります。
これを手計算でやるのは骨が折れるので、適当にC言語のプログラムを書くことにします。
はい、こちらが出来上がったプログラムになります!(3分クッキング風)
さて、これを用いてスコア999,999を出すために必要なC,Wを求めてみよう!
ポチッとな!
"解なし"
知ってた。
不定方程式
(1.01C+0.5W)*(1000000/1499)=1000000 ⑶
にはC=0,W=2998という整数解が存在します。
C,Wを整数とすれば、(1.01C+0.5W)の部分は、最小でも0.01単位でしか動かすことができません。1000000/1499>667なので、(1.01C+0.5W)*(1000000/1499)は最小でも6.67単位でしか動かせません。
つまり、⑶に整数解が存在する時点で、⑴'を満たす非負整数C,Wが存在しないことは容易に予想できるのです。
(これは、10,000ノーツ以上ある曲ではスコア999,999を出せるとも解釈できます。今の所そんな曲はありませんが)
どうしよう…このままじゃ企画倒れだなぁ
…
⑨でしょ?まるきゅうでしょ?0が入ってもいいよね…!
0が一個入った999990,999909,999099,990999,909999について先ほどのプログラムで調べてみると…
999099に解があるらしい!
でもこのスコア、自分のハイスコアに近くて出すこと自体が少し難しい。
出せないものはしょうがないのでさらに妥協して0を二個入れることにすると、909099に解が見つかった。
これなら行ける!
解の1つはC=1274,W=152であり、これを目指すことにしよう。
意気揚々とゲーセンに行きやってみたが…
全然できない。C=1274はまだしも、W=152がとても難しい。JUSTICE CRITICAL、JUSTICE、ATTACKの3つのパラメータを管理しなければならないのはとても厳しい。(MISSはスコアに関係ないしほっとけば出るので無視)
どうすっかな、、、
ここで私はあるスキルに目をつけた。(スキルとは、CHUNITHMの要素のひとつである「マップ」を進めるために必要な「ゲージ」を溜める時に、様々な効果をもたらすものです)
その名も"アタックブレイク"。これはATTACKの判定がMISSになるというもので、必然的にA=0とすることができる。
こうすれば、管理するパラメータはJUSTICE CRITICALとJUSTICEの2つとなり、出しやすくなるはず!
目標値はC=1174,J=177,A=0,M=148に設定。
3クレほど回してみた。さっきよりはやりやすいけど、数値の調整はやはりむずかしいね。狙ってJUSTICEを出すのがとても難しい。たまたま嵌るのを待つしかない気がしてきた。
ここまでの文章を書いたのが12月頭だったのだが…結局今日に至るまで出せていないんだよなぁ。いつか出せたら私のTwitter(@maiyaline)で報告しますね。
ではでは〜
使ったプログラムのソースコード(解さえ求まれば良いのでガバガバなんだな)
#include<stdio.h>
int get_notes()
{
int notes;
printf("Please input notes.\n");
scanf("%d",¬es);/*楽曲のノーツ数を取得*/
return(notes);
}
int get_score()
{
int score;
printf("Please input score.\n");
scanf("%d",&score);/*目標スコアを取得*/
return(score);
}
int search(int notes,int score)
{
double piece;
double value;
int i = 0;
piece = 1000000.0/notes;/*1ノーツあたりの点数を計算*/
for(int c = 0;c <= notes;c++)
{
for(int w = 0;w <= 2 * (notes - c);w++)
{
value = piece * (1.01 * c + 0.5 * w);/*対応するスコアを計算*/
if((score <= value) && (value < score + 1))
{
printf("%d,%d\n",c,w);/*目標スコアと一致すれば出力*/
i = i + 1;/*解の個数をカウント*/
}
}
}
if(i == 0)
{
printf("解なし\n");
}
return 0;
}
int main(void)
{
int notes;
int score;
notes = get_notes();
score = get_score();
search(notes,score);
return 0;
}