人生で影響を受けた本100冊。
https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e
4番目の本のプログラマ編。
4. だるまちゃんとてんぐちゃん
1967/11 加古里子(かこさとし)

https://www.amazon.co.jp/dp/4834001245/
https://bookmeter.com/books/550529
https://booklog.jp/item/1/4834001245
日本の物語らしい「だるまちゃん」と「てんぐちゃん」の物語。
ほのぼのとした雰囲気と、ゆったりとした進行。
自分で読むなら、小学校進学前の子供によい。
読み聞かせには、0歳から3歳くらいまでがお勧め。
p.s.
小坂井大輔が名古屋駅前で開催していた読書会で取り上げた方がおみえになった。
自分で読んだことがあったが、何気なく奥付を見たら「技術士」と書いてあった。
自分の知っている技術士で、一番たくさん本を書いた人だと思った。
技術士の書いた本1000冊 researchmap 資料一覧(かこさとしの300冊以上を含む)
https://qiita.com/kaizen_nagoya/items/02286b43bfc9799f394b
ChatGPT
だるまちゃんとてんぐちゃん 加古里子 らプログラマが学ぶとよい視点を7つご紹介ください。
ChatGPT:
もちろんです。絵本『だるまちゃんとてんぐちゃん』(加古里子)は、子ども向けですが、プログラマが学ぶとよい視点を引き出すことができます。以下に7つの視点を挙げます。
- シンプルさの美学
絵本の特徴: キャラクターや場面がシンプルで分かりやすい。
プログラマの学び: コードもシンプルであることが可読性・保守性に直結します。不要な複雑さを避ける習慣をつける。 - モジュール化・役割分担
絵本の特徴: だるまちゃんとてんぐちゃん、それぞれ役割が明確。
プログラマの学び: クラスや関数を役割ごとに分けることで、再利用性や保守性が向上する。 - 変化の可視化
絵本の特徴: 動きや変化(だるまの転がる様子、てんぐの飛ぶ様子)が視覚的に表現されている。
プログラマの学び: データの変化やフローを可視化すると、バグの原因特定や理解が早くなる。 - ユーザー視点(子ども視点)
絵本の特徴: 読者が主人公の気持ちを体験できるよう描かれている。
プログラマの学び: UI/UX設計ではユーザー視点を重視し、使いやすさを最優先する。 - 逐次的なストーリー進行
絵本の特徴: 行動の順序がわかりやすく、一歩ずつ展開する。
プログラマの学び: アルゴリズムや処理のステップを明確に順序立てて設計する習慣がつく。 - エラーや例外の扱い
絵本の特徴: だるまちゃんが転がるなど、予期せぬハプニングも描かれる。
プログラマの学び: 例外処理やエラーへの対応をコード設計に組み込む重要性を学べる。 - 遊び心・柔軟な発想
絵本の特徴: ユーモアや奇想天外な動きがある。
プログラマの学び: 柔軟な発想や遊び心は、新しいアイデアや効率的な解決策の源になる。
もしご希望であれば、これらの7つの視点を 具体的なプログラム設計例(C++ / Rust) で示すこともできます。
作ってほしいですか?
はい。お願いします。
ChatGPT:
では、先ほどの7つの視点をもとに、C++ と Rust で簡単なプログラム例を示します。
絵本の「だるまちゃんとてんぐちゃん」のキャラクターの動きや関係をコードで表現する形にしています。
- C++例
#include <iostream>
#include <string>
#include <vector>
// モジュール化: キャラクターをクラスで表現
class Character {
public:
std::string name;
int position;
Character(std::string n, int p = 0) : name(n), position(p) {}
void move(int steps) {
position += steps;
std::cout << name << " moves to " << position << std::endl;
}
void react(const std::string& event) {
std::cout << name << " reacts to " << event << std::endl;
}
};
int main() {
Character daruma("Daruma");
Character tengu("Tengu", 5);
// ストーリー進行: 逐次的な動き
daruma.move(3);
tengu.move(-2);
// 例外・予期せぬハプニング
try {
if(daruma.position < 0) throw std::runtime_error("Daruma fell off!");
} catch(const std::runtime_error &e) {
daruma.react(e.what());
}
// 遊び心: ランダムな動き
std::vector<int> moves = {1, 2, -1};
for(auto m : moves) daruma.move(m);
return 0;
}
'2. Rust例
struct Character {
name: String,
position: i32,
}
impl Character {
fn new(name: &str, position: i32) -> Self {
Self { name: name.to_string(), position }
}
fn move_by(&mut self, steps: i32) {
self.position += steps;
println!("{} moves to {}", self.name, self.position);
}
fn react(&self, event: &str) {
println!("{} reacts to {}", self.name, event);
}
}
fn main() {
let mut daruma = Character::new("Daruma", 0);
let mut tengu = Character::new("Tengu", 5);
// 逐次的なストーリー進行
daruma.move_by(3);
tengu.move_by(-2);
// エラー処理
if daruma.position < 0 {
daruma.react("Daruma fell off!");
}
// 遊び心: ランダムな動き
let moves = vec![1, 2, -1];
for m in moves {
daruma.move_by(m);
}
}
🔑 ポイント
シンプルさ → キャラクタークラスだけで最小限の動きを表現。
モジュール化 → Character クラスに move/react をまとめる。
逐次的進行 → main関数内で動作順序をわかりやすく。
ユーザー視点 → 標準出力で動きや反応を「見える化」。
エラー処理 → 予期せぬ動きに対応。
遊び心 → ランダムな動きや反応を追加。
可視化 → 位置情報を表示し、動作を理解しやすく。
希望であれば、このプログラムを だるまちゃんとてんぐちゃんの「協力」や「相互作用」まで表現して、小さな物語風に動かす拡張版 も作れます。
作りますか?
はい。お願いします。
ChatGPT:
では、だるまちゃんとてんぐちゃんが 協力してタスクを達成する小さな物語風プログラム を C++ と Rust で作ります。
ポイントは「相互作用」と「役割分担」を表現することです。
- C++版:協力して山を登る物語
#include <iostream>
#include <string>
class Character {
public:
std::string name;
int position;
Character(std::string n, int p = 0) : name(n), position(p) {}
void move(int steps) {
position += steps;
std::cout << name << " moves to " << position << std::endl;
}
void help(Character &other, int steps) {
other.position += steps;
std::cout << name << " helps " << other.name << " move to " << other.position << std::endl;
}
void react(const std::string &event) {
std::cout << name << " reacts to " << event << std::endl;
}
};
int main() {
Character daruma("Daruma");
Character tengu("Tengu", 3);
std::cout << "=== 小さな冒険:山登り ===" << std::endl;
// ステップ1: それぞれ動く
daruma.move(2);
tengu.move(1);
// ステップ2: 協力
daruma.help(tengu, 2);
tengu.help(daruma, 1);
// ステップ3: ハプニング
try {
if(daruma.position < 0) throw std::runtime_error("Daruma slipped!");
if(tengu.position < 0) throw std::runtime_error("Tengu slipped!");
} catch(const std::runtime_error &e) {
daruma.react(e.what());
tengu.react(e.what());
}
// ステップ4: ゴール
std::cout << "Daruma reaches " << daruma.position << std::endl;
std::cout << "Tengu reaches " << tengu.position << std::endl;
std::cout << "=== 協力して山を登りきりました! ===" << std::endl;
return 0;
}
'2. Rust版:協力して山を登る物語
struct Character {
name: String,
position: i32,
}
impl Character {
fn new(name: &str, position: i32) -> Self {
Self { name: name.to_string(), position }
}
fn move_by(&mut self, steps: i32) {
self.position += steps;
println!("{} moves to {}", self.name, self.position);
}
fn help(&mut self, other: &mut Character, steps: i32) {
other.position += steps;
println!("{} helps {} move to {}", self.name, other.name, other.position);
}
fn react(&self, event: &str) {
println!("{} reacts to {}", self.name, event);
}
}
fn main() {
let mut daruma = Character::new("Daruma", 0);
let mut tengu = Character::new("Tengu", 3);
println!("=== 小さな冒険:山登り ===");
// ステップ1: それぞれ動く
daruma.move_by(2);
tengu.move_by(1);
// ステップ2: 協力
daruma.help(&mut tengu, 2);
tengu.help(&mut daruma, 1);
// ステップ3: ハプニング
if daruma.position < 0 {
daruma.react("Daruma slipped!");
}
if tengu.position < 0 {
tengu.react("Tengu slipped!");
}
// ステップ4: ゴール
println!("Daruma reaches {}", daruma.position);
println!("Tengu reaches {}", tengu.position);
println!("=== 協力して山を登りきりました! ===");
}
🔑 ポイント
協力(help関数) → キャラクター同士が互いに影響を与える。
逐次的なストーリー進行 → 動き、協力、ハプニング、ゴールの順に整理。
例外・反応 → ハプニングに対応。
遊び心 → 簡単な山登りの冒険風に表現。
役割分担 → DarumaとTenguそれぞれが動きとサポートを担当。
可視化 → 標準出力で状態を確認。
もし希望なら、さらに だるまちゃんとてんぐちゃんが「判断」や「戦略」を考えながら協力するAI的シミュレーション版 に進化させることもできます。
作りますか?
はい。お願いします。
ChatGPT:
では、だるまちゃんとてんぐちゃんが 判断や戦略を考えながら協力する簡単なAI的シミュレーション を作ります。
ポイントは「行動の優先順位」「状態に応じた判断」「協力戦略」です。
- C++版:判断付き協力シミュレーション
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
class Character {
public:
std::string name;
int position;
int energy;
Character(std::string n, int p = 0) : name(n), position(p), energy(10) {}
// 戦略的な移動
void decide_move() {
if(energy > 3) {
int steps = rand() % 3 + 1; // 1〜3歩
move(steps);
energy -= 2;
} else {
std::cout << name << " is resting to recover energy." << std::endl;
energy += 2;
}
}
void move(int steps) {
position += steps;
std::cout << name << " moves " << steps << " steps to " << position << std::endl;
}
void help(Character &other) {
if(energy > 2) {
int assist = 1 + rand() % 2;
other.position += assist;
std::cout << name << " helps " << other.name << " move " << assist << " steps to " << other.position << std::endl;
energy -= 2;
}
}
bool reached_goal(int goal) {
return position >= goal;
}
};
int main() {
srand((unsigned)time(0));
Character daruma("Daruma");
Character tengu("Tengu", 2);
int goal = 10;
std::cout << "=== 協力シミュレーション:山登り ===" << std::endl;
int turn = 1;
while(!daruma.reached_goal(goal) && !tengu.reached_goal(goal)) {
std::cout << "--- Turn " << turn << " ---" << std::endl;
// 戦略的判断
daruma.decide_move();
tengu.decide_move();
// 協力
if(rand() % 2) daruma.help(tengu);
else tengu.help(daruma);
turn++;
}
std::cout << "Daruma reaches " << daruma.position << ", Tengu reaches " << tengu.position << std::endl;
std::cout << "=== ゴールに到達しました! ===" << std::endl;
return 0;
}
- Rust版:判断付き協力シミュレーション
use rand::Rng;
struct Character {
name: String,
position: i32,
energy: i32,
}
impl Character {
fn new(name: &str, position: i32) -> Self {
Self { name: name.to_string(), position, energy: 10 }
}
fn decide_move(&mut self) {
if self.energy > 3 {
let steps = rand::thread_rng().gen_range(1..=3);
self.move_by(steps);
self.energy -= 2;
} else {
println!("{} is resting to recover energy.", self.name);
self.energy += 2;
}
}
fn move_by(&mut self, steps: i32) {
self.position += steps;
println!("{} moves {} steps to {}", self.name, steps, self.position);
}
fn help(&mut self, other: &mut Character) {
if self.energy > 2 {
let assist = rand::thread_rng().gen_range(1..=2);
other.position += assist;
println!("{} helps {} move {} steps to {}", self.name, other.name, assist, other.position);
self.energy -= 2;
}
}
fn reached_goal(&self, goal: i32) -> bool {
self.position >= goal
}
}
fn main() {
let mut daruma = Character::new("Daruma", 0);
let mut tengu = Character::new("Tengu", 2);
let goal = 10;
println!("=== 協力シミュレーション:山登り ===");
let mut turn = 1;
while !daruma.reached_goal(goal) && !tengu.reached_goal(goal) {
println!("--- Turn {} ---", turn);
daruma.decide_move();
tengu.decide_move();
if rand::thread_rng().gen_bool(0.5) {
daruma.help(&mut tengu);
} else {
tengu.help(&mut daruma);
}
turn += 1;
}
println!("Daruma reaches {}, Tengu reaches {}", daruma.position, tengu.position);
println!("=== ゴールに到達しました! ===");
}
🔑 学びのポイント
判断力 → エネルギーや状況に応じて「動く」か「休む」を決める。
協力戦略 → 相手を助けることでチーム全体のゴール達成を目指す。
逐次的進行 → ターン制でストーリーの流れを表現。
状態管理 → position や energy を追跡。
遊び心・可視化 → 標準出力で動きや協力行動を見える化。
不確定要素 → ランダム性で「判断」や「助け方」に変化を持たせる。
もし希望であれば、次のステップとして だるまちゃんとてんぐちゃんが「役割を交代」したり「戦略を改善」しながらゴールまで最適化するシミュレーション に進化させることもできます。
作りますか?
はい。お願いします。
ChatGPT:
では次のステップとして、だるまちゃんとてんぐちゃんが 役割を交代したり、戦略を改善しながらゴールまで効率的に進むシミュレーション を作ります。
ポイントは「協力の最適化」「学習的行動」「役割の動的変更」です。
- C++版:戦略改善シミュレーション
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
class Character {
public:
std::string name;
int position;
int energy;
bool is_leader;
Character(std::string n, int p = 0, bool leader = false)
: name(n), position(p), energy(10), is_leader(leader) {}
void decide_move(Character &other, int goal) {
// 戦略: 体力が多く、リーダーなら積極的に動く
if(energy > 4 && is_leader) {
move(std::min(3, goal - position));
energy -= 2;
} else if(energy > 2) {
move(1);
energy -= 1;
} else {
std::cout << name << " is resting." << std::endl;
energy += 2;
}
// 助ける優先度: 相手がリーダーでない場合
if(other.position < position && energy > 2) {
help(other);
}
}
void move(int steps) {
position += steps;
std::cout << name << " moves " << steps << " steps to " << position << std::endl;
}
void help(Character &other) {
other.position += 1;
energy -= 2;
std::cout << name << " helps " << other.name << " to " << other.position << std::endl;
}
void switch_role(Character &other) {
// 役割を交代
if(position > other.position && energy < other.energy) {
is_leader = false;
other.is_leader = true;
std::cout << name << " switches role with " << other.name << std::endl;
}
}
bool reached_goal(int goal) {
return position >= goal;
}
};
int main() {
srand((unsigned)time(0));
Character daruma("Daruma", 0, true);
Character tengu("Tengu", 2);
int goal = 10;
int turn = 1;
std::cout << "=== 協力+戦略改善シミュレーション ===" << std::endl;
while(!daruma.reached_goal(goal) && !tengu.reached_goal(goal)) {
std::cout << "--- Turn " << turn << " ---" << std::endl;
daruma.decide_move(tengu, goal);
tengu.decide_move(daruma, goal);
// 役割交代
daruma.switch_role(tengu);
turn++;
}
std::cout << "Daruma reaches " << daruma.position << ", Tengu reaches " << tengu.position << std::endl;
std::cout << "=== ゴールに到達!効率的な協力でした ===" << std::endl;
return 0;
}
- Rust版:戦略改善シミュレーション
use rand::Rng;
struct Character {
name: String,
position: i32,
energy: i32,
is_leader: bool,
}
impl Character {
fn new(name: &str, position: i32, is_leader: bool) -> Self {
Self { name: name.to_string(), position, energy: 10, is_leader }
}
fn decide_move(&mut self, other: &mut Character, goal: i32) {
if self.energy > 4 && self.is_leader {
let steps = (3).min(goal - self.position);
self.move_by(steps);
self.energy -= 2;
} else if self.energy > 2 {
self.move_by(1);
self.energy -= 1;
} else {
println!("{} is resting.", self.name);
self.energy += 2;
}
if other.position < self.position && self.energy > 2 {
self.help(other);
}
}
fn move_by(&mut self, steps: i32) {
self.position += steps;
println!("{} moves {} steps to {}", self.name, steps, self.position);
}
fn help(&mut self, other: &mut Character) {
other.position += 1;
self.energy -= 2;
println!("{} helps {} to {}", self.name, other.name, other.position);
}
fn switch_role(&mut self, other: &mut Character) {
if self.position > other.position && self.energy < other.energy {
self.is_leader = false;
other.is_leader = true;
println!("{} switches role with {}", self.name, other.name);
}
}
fn reached_goal(&self, goal: i32) -> bool {
self.position >= goal
}
}
fn main() {
let mut daruma = Character::new("Daruma", 0, true);
let mut tengu = Character::new("Tengu", 2, false);
let goal = 10;
let mut turn = 1;
println!("=== 協力+戦略改善シミュレーション ===");
while !daruma.reached_goal(goal) && !tengu.reached_goal(goal) {
println!("--- Turn {} ---", turn);
daruma.decide_move(&mut tengu, goal);
tengu.decide_move(&mut daruma, goal);
daruma.switch_role(&mut tengu);
turn += 1;
}
println!("Daruma reaches {}, Tengu reaches {}", daruma.position, tengu.position);
println!("=== ゴールに到達!効率的な協力でした ===");
}
🔑 学びのポイント
役割の動的変更 → リーダーを交代することでエネルギー効率を最適化。
戦略改善 → 状況に応じて「動く」「休む」「助ける」を判断。
協力の最適化 → 助け合いで全体のゴール到達を効率化。
学習的行動 → 状態(エネルギーや位置)に応じて行動を変える。
可視化 → 標準出力で戦略と役割の変化を確認可能。
遊び心 → 小さな冒険+協力戦略の物語をシミュレーション。
もし希望であれば、次のステップとして 複数ターンを通して「最適な戦略パターン」を自動で探索するAIシミュレーション版 に進化させることもできます。
作りますか?
ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。