あけましておめでとうございます。ことしもよろしくお願いします。
おじさん、毎年この時期に新聞とかに載っている入試問題をといています。
暇つぶしに解いていたら、なんと中学入試の問題にプログラムコンテストの問題が混じっているではないか!
https://www10.schoolweb.ne.jp/weblog/files/1320077/doc/86294/1393171.pdf
このPDFの10ページの[2]の問2。
おじさん、年とともにどんどん問題を解くのに時間がかかり、解けなくなっていきます。かなしい。
この問題、たぶん3分くらいでとけないといけないのですが、24時間以上間考えてもわからない。
おじさん忠実に問題を解いていますが、この問題、相当難しい。
問題を複雑にしているポイントは3つ。
一つ目は、赤色+赤色の定義。
「赤色+赤色」を「赤色+赤色=赤色」とするのか、「赤色+赤色=2×赤色」とするのか演算処理が定義がされていない。
加法混色で赤色と青色と緑色がそれぞれ個数に関係なく兎に角3種類あれば白色なのか。
赤色と青色と緑色が同じ数だけある場合のみが白色なのか。
別の言い方をすると、「赤色+赤色+緑色+青色」を白色と扱うかピンクっぽい色って扱うか。
二つ目は、使って良いかい中電灯の個数。
かい中電灯を何個使っていいか問題には書かれていない。
仮にかい中電灯を2個だけでなく3個以上使って良く、かつ、「赤色+赤色=赤色」を定義する場合、結構な数の組み合わせになる。
ためしに答案用紙の広さを見ると一行分しかないじゃない。
超ちっちゃく書かないと答案用紙にはいらない!
三つ目は灰色を使うかどうか。
「赤色+緑色+青色」を白色と定義した場合、「2×赤色+2×緑色+2×青色」という白色を超える白色のパターンがでてしまう。これを白色とするのか、それとも「赤色+緑色+青色」を灰色として「2×赤色+2×緑色+2×青色」のみを白色とするのか。
白色と黒色と灰色って定義が難しい。
この問題、そもそも一つ目の問題を後者として問題を解くと答えの総数が減るんですが、灰色問題が出てきてしまって問題がとけない。一つ目の問題を前者として問題を解くと答えの総数が多くて大変なことになります。
なので、ありそうな答えの込み合わせをすべてプログラムで組んでみました。
----------------------------
#include <stdio.h>
#include <string.h>
#define R 1
#define G 10
#define B 100
int kaicyu[] = {
R,G,R + G, R+B,G+B
};
const char* name[] = {
"赤色","緑色","黄色","赤むらさき色","空色"
};
#define isR(a) (a%10)
#define isG(a) ((a/10)%10)
#define isB(a) ((a/100)%10)
#define syokusu(a) (((a&1)!=0)+((a&2)!=0)+((a&4)!=0)+((a&8)!=0)+((a&16)!=0))
int main()
{
int i, c, m, j;
char buf[256];
printf("ptn1\n");
printf("----------\n");
for (i = 1; i <= 31; i++)
{
buf[0] = 0;
c = 0;
for (m = 1, j = 0; j < 5; j++, m <<= 1) {
if (i & m) {
c += kaicyu[j];
if (buf[0] != 0)strcat(buf, "と");
strcat(buf, name[j]);
}
}
if (isR(c) && isG(c) && isB(c)) {
printf("%s\n", buf);
}
}
printf("\n");
printf("ptn2\n");
printf("----------\n");
for (i = 1; i <= 31; i++)
{
buf[0] = 0;
c = 0;
for (m = 1, j = 0; j < 5; j++, m <<= 1) {
if (i & m) {
c += kaicyu[j];
if (buf[0] != 0)strcat(buf, "と");
strcat(buf, name[j]);
}
}
if (isR(c) == isG(c) && isR(c) == isB(c)) {
printf("%s\n", buf);
}
}
printf("\n");
printf("ptn3\n");
printf("----------\n");
for (i = 1; i <= 31; i++)
{
buf[0] = 0;
c = 0;
for (m = 1, j = 0; j < 5; j++, m <<= 1) {
if (i & m) {
c += kaicyu[j];
if (buf[0] != 0)strcat(buf, "と");
strcat(buf, name[j]);
}
}
if (isR(c) == 2 && isG(c) == 2 && isB(c) == 2) {
printf("%s\n", buf);
}
}
printf("\n");
printf("ptn4\n");
printf("----------\n");
for (i = 1; i <= 31; i++)
{
buf[0] = 0;
c = 0;
for (m = 1, j = 0; j < 5; j++, m <<= 1) {
if (i & m) {
c += kaicyu[j];
if (buf[0] != 0)strcat(buf, "と");
strcat(buf, name[j]);
}
}
if (isR(c) == 1 && isG(c) == 1 && isB(c) == 1) {
printf("%s\n", buf);
}
}
printf("\n");
printf("ptn5\n");
printf("----------\n");
for (i = 1; i <= 31; i++)
{
buf[0] = 0;
c = 0;
for (m = 1, j = 0; j < 5; j++, m <<= 1) {
if (i & m) {
c += kaicyu[j];
if (buf[0] != 0)strcat(buf, "と");
strcat(buf, name[j]);
}
}
if (syokusu(i)==2 && isR(c) && isG(c) && isB(c) ) {
printf("%s\n", buf);
}
}
printf("\n");
return 0;
}
----------------------------
----------------------------
ptn1
----------
緑色と赤むらさき色
赤色と緑色と赤むらさき色
黄色と赤むらさき色
赤色と黄色と赤むらさき色
緑色と黄色と赤むらさき色
赤色と緑色と黄色と赤むらさき色
赤色と空色
赤色と緑色と空色
黄色と空色
赤色と黄色と空色
緑色と黄色と空色
赤色と緑色と黄色と空色
赤むらさき色と空色
赤色と赤むらさき色と空色
緑色と赤むらさき色と空色
赤色と緑色と赤むらさき色と空色
黄色と赤むらさき色と空色
赤色と黄色と赤むらさき色と空色
緑色と黄色と赤むらさき色と空色
赤色と緑色と黄色と赤むらさき色と空色
ptn2
----------
緑色と赤むらさき色
赤色と空色
赤色と緑色と赤むらさき色と空色
黄色と赤むらさき色と空色
ptn3
----------
赤色と緑色と赤むらさき色と空色
黄色と赤むらさき色と空色
ptn4
----------
緑色と赤むらさき色
赤色と空色
ptn5
----------
緑色と赤むらさき色
黄色と赤むらさき色
赤色と空色
黄色と空色
赤むらさき色と空色
----------------------------
中学校の入学試験ってとっても難しい。
うーん、これ本当にとけた小学生いるのだろうか・・・。
どれが正解なんだ???。
SAPIXの先生か誰か答えを教えてください。