1. ホーム >
  2. 電子書籍 >
  3. プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問


形式:
電子書籍
発売日:
ISBN:
9784798143507
価格:
本体2,580円+税

本書籍の他の形式を確認する

  • このエントリーをはてなブックマークに追加

パズルを解くコードを、あなたは書けるか?
アルゴリズムがみるみるわかる!プログラミングってやっぱり面白い!

急速な技術の進歩、システム開発競争の激化……。プログラマを取り巻く環境はやさしいものではありません。でも、思い出してみてください。自分の書いたソースコードでプログラムが動くのを初めて見たとき。思い描いた通りのプログラムができたとき。プログラミングの楽しさを感じたことでしょう。何もないところからソースコードだけで新たな価値を生むプログラマは、非常に魅力的な職業です。

本書で登場する数学パズルは、そのようなワクワクにあふれています。「両替したときの硬貨の組み合わせはいくつ?」のような問題から、「国名でしりとりしたときに、一番長く続く順番は?」「運命の出会いは何通り?」というものまで、70の問題を解くコードを、3人のキャラクターたちと一緒に考えていきます。

パズルを解くうちにアルゴリズムが身につき、シンプルで高速なコードが書けるようになります。楽しみながらスキルアップもできて一石二鳥。さっそく挑戦してみましょう!

【使用言語について】
本書の解説では、主にRubyとJavaScriptを使用していますが、解説内容は「考え方」が中心であるため、どんな言語にも応用できます。また、問題を解くために特定の言語が必要になることもありません。

【本書に収録されている問題(抜粋)】
Q01 10進数で回文
Q03 カードを裏返せ
Q08 優秀な掃除ロボット
Q09 つりあわない男女
Q21 排他的論理和で作る三角形
Q33 百人一首の達人
Q45 素数のマトリックス
Q48 グレイコードのループ
Q53 いたずらされたお菓子
Q64 迷路で待ち合わせ

※本電子書籍は同名出版物を底本として作成しました。記載内容は印刷出版当時のものです。
※印刷出版再現のため電子書籍としては不要な情報を含んでいる場合があります。
※印刷出版とは異なる表記・表現の場合があります。予めご了承ください。
※プレビューにてお手持ちの電子端末での表示状態をご確認の上、商品をお買い求めください。

(翔泳社)

目次の登録はありません。

付属データはこちら

書籍への問い合わせ

正誤表、追加情報をご確認の上、こちらよりお問い合わせください

書影の利用許諾について

本書籍に関する利用許諾申請はこちらになります

追加情報はありません。

本書に誤りまたは不十分な記述がありました。下記のとおり訂正し、お詫び申し上げます。

書籍・SEshop限定PDF:ご購入刷数  電子書籍 最終更新日:2016年11月16日
発生刷 ページ数 書籍改訂刷 電子書籍訂正 内容 登録日
1刷 041
Q09 問題文
3刷
2つのグループのいずれかで男女の数が異なってしまう
2つのグループのいずれも男女の数が異なってしまう
2015.12.16
1刷 088
Q19 解答の補記
3刷
これを満たす組み合わせは以下のようになります。
これを満たす組み合わせの例は以下のようになります。
2015.12.10
1刷 100
Q23 ソースコード(q23_01.rb)の5行目と6行目
3刷
return 1 if depth == 0 return 0 if coin == 0
return 0 if coin == 0 return 1 if depth == 0

第3刷発行にあわせ、ダウンロードファイルを修正しました(2016.3.3)
2015.11.11
1刷 100
Q23 解答
3刷
16195220通り
16051010通り
2015.11.11
1刷 124
Q30 ソースコード(q30_01.rb)
3刷
N = 20

def set_tap(remain)
return 1 if remain == 1
cnt = 0
# 2口
(1..(remain / 2)).each{|i|
cnt += set_tap(remain - i) * set_tap(i)
}
# 3口
(1..(remain / 3)).each{|i|
(1..((remain - i) / 2)).each{|j|
cnt += set_tap(remain - (i + j)) * set_tap(j) * set_tap(i)
}
}
cnt
end
puts set_tap(N)
N = 20

def set_tap(remain)
return 1 if remain == 1
cnt = 0
# 2口
(1..(remain / 2)).each{|i|
if remain - i == i then
cnt += set_tap(i) * (set_tap(i) + 1) / 2
else
cnt += set_tap(remain - i) * set_tap(i)
end
}
# 3口
(1..(remain / 3)).each{|i|
(i..((remain - i) / 2)).each{|j|
if (remain - (i + j) == i) && (i == j) then
cnt += set_tap(i) * (set_tap(i) + 1) * (set_tap(i) + 2) / 6
elsif remain - (i + j) == i then
cnt += set_tap(i) * (set_tap(i) + 1) * set_tap(j) / 2
elsif i == j then
cnt += set_tap(remain - (i+j)) * set_tap(i) * (set_tap(i)+1) / 2
elsif remain - (i + j) == j then
cnt += set_tap(j) * (set_tap(j) + 1) * set_tap(i) / 2
else
cnt += set_tap(remain - (i + j)) * set_tap(j) * set_tap(i)
end
}
}
cnt
end
puts set_tap(N)

第3刷発行にあわせ、ダウンロードファイルを修正しました(2016.3.3)
2015.11.25
1刷 125
Q30 ソースコード(q30_02.rb)
3刷
N = 20
@memo = {1 => 1}

def set_tap(remain)
return @memo[remain] if @memo.has_key?(remain)
cnt = 0
# 2口
(1..(remain / 2)).each{|i|
cnt += set_tap(remain - i) * set_tap(i)
}
# 3口
(1..(remain / 3)).each{|i|
(1..((remain - i) / 2)).each{|j|
cnt += set_tap(remain - (i + j)) * set_tap(j) * set_tap(i)
}
}
@memo[remain] = cnt
end

puts set_tap(N)
N = 20

@memo = {1 => 1}
def set_tap(remain)
return @memo[remain] if @memo.has_key?(remain)
cnt = 0
# 2口
(1..(remain / 2)).each{|i|
if remain - i == i then
cnt += set_tap(i) * (set_tap(i) + 1) / 2
else
cnt += set_tap(remain - i) * set_tap(i)
end
}
# 3口
(1..(remain / 3)).each{|i|
(i..((remain - i) / 2)).each{|j|
if (remain - (i + j) == i) && (i == j) then
cnt += set_tap(i) * (set_tap(i) + 1) * (set_tap(i) + 2) / 6
elsif remain - (i + j) == i then
cnt += set_tap(i) * (set_tap(i) + 1) * set_tap(j) / 2
elsif i == j then
cnt += set_tap(remain - (i+j)) * set_tap(i) * (set_tap(i)+1) / 2
elsif remain - (i + j) == j then
cnt += set_tap(j) * (set_tap(j) + 1) * set_tap(i) / 2
else
cnt += set_tap(remain - (i + j)) * set_tap(j) * set_tap(i)
end
}
}
@memo[remain] = cnt
end

puts set_tap(N)

第3刷発行にあわせ、ダウンロードファイルを修正しました(2016.3.3)
2015.11.25
1刷 126
Q30 ソースコード(q30_03.js)
3刷
const N = 20;
var memo = [];
memo[1] = 1;

function set_tap(remain){
if (memo[remain]){
return memo[remain];
}
var cnt = 0;
/* 2口 */
for (var i = 1; i <= remain / 2; i++){
cnt += set_tap(remain - i) * set_tap(i);
}
/* 3口 */
for (var i = 1; i <= remain / 3; i++){
for (var j = 1; j <= (remain - i) / 2; j++){
cnt += set_tap(remain - (i + j)) * set_tap(j) * set_tap(i);
}
}
memo[remain] = cnt;
return cnt;
}

console.log(set_tap(N));
const N = 20;
var memo = [];
memo[1] = 1;

function set_tap(remain){
if (memo[remain]){
return memo[remain];
}
var cnt = 0;
/* 2口 */
for (var i = 1; i <= remain / 2; i++){
if (remain - i == i)
cnt += set_tap(i) * (set_tap(i) + 1) / 2;
else
cnt += set_tap(remain - i) * set_tap(i);
}
/* 3口 */
for (var i = 1; i <= remain / 3; i++){
for (var j = i; j <= (remain - i) / 2; j++){
if ((remain - (i + j) == i) && (i == j))
cnt += set_tap(i) * (set_tap(i) + 1) * (set_tap(i) + 2) / 6;
else if (remain - (i + j) == i)
cnt += set_tap(i) * (set_tap(i) + 1) * set_tap(j) / 2;
else if (i == j)
cnt += set_tap(remain - (i+j)) * set_tap(i) * (set_tap(i)+1) / 2;
else if (remain - (i + j) == j)
cnt += set_tap(j) * (set_tap(j) + 1) * set_tap(i) / 2;
else
cnt += set_tap(remain - (i + j)) * set_tap(j) * set_tap(i);
}
}
memo[remain] = cnt;
return cnt;
}

console.log(set_tap(N));

第3刷発行にあわせ、ダウンロードファイルを修正しました(2016.3.3)
2015.11.25
1刷 126
Q30 解答
3刷
136916765通り
63877262通り
2015.11.25
1刷 212
Q51 解答
3刷
①2(n-1)回で「初めて」元に戻ったとき、46個 ②何度も元に戻るが、2(n-1)回のときも元に戻ったとき、22個
①2(n-1)回で「初めて」元に戻ったとき、22個 ②何度も元に戻るが、2(n-1)回のときも元に戻ったとき、46個
2015.12.10
1刷 212
Q51のPoint内、下から3つ目の式
(i×2)^2(n-1)mod(2×n-1)=i
i×2^2(n-1)mod(2×n-1)= i
2016.11.16