この Lab では1~2人のクラスメートと協力することは問題ありませんが、そのグループのすべての受講生が等しく実習に貢献することが求められます。
家族の各メンバーの血液型の継承をシミュレートします。
$ ./inheritance
Child (Generation 0): blood type OO
Parent (Generation 1): blood type AO
Grandparent (Generation 2): blood type OA
Grandparent (Generation 2): blood type BO
Parent (Generation 1): blood type OB
Grandparent (Generation 2): blood type AO
Grandparent (Generation 2): blood type BO
背景
人の血液型は2つの対立遺伝子 (異なる形態の遺伝子) によって決まります。可能性のある3つの対立遺伝子はA、B、Oであり、それぞれの人は2つ (同じかもしれないし、違うかもしれません) をもちます。子供の両親はそれぞれ、2つの血液型対立遺伝子の1つを子供にランダムに渡します。したがって、考えられる血液型の組み合わせは、OO、OA、OB、AO、AA、AB、BO、BA、およびBBです。
たとえば、片方の親の血液型がAOで、もう一方の親の血液型がBBである場合、それぞれの親からどの対立遺伝子を受け取るかによって、子の血液型はABまたはOBになります。同様に、片方の親の血液型がAOで、もう一方がOBである場合、子の血液型はAO、OB、AB、およびOOになります。
始め方
VS Codeを開きます。
ターミナルウィンドウ内をクリックすることから始めて、それからcd
を実行します。
その後プロンプトは次のようになっていることがわかります。
$
ターミナルウィンドウの内側をクリックし、次のように入力します。
wget https://cdn.cs50.net/2021/fall/labs/5/inheritance.zip
その後にEnterを押すと、inheritance.zipというZIPがあなたのCodespaceにダウンロードされます。wgetと次のURLの間にあるスペースや、その他の文字を見落とさないように注意してください。
次に
unzip inheritance.zip
を実行して、inheritanceというフォルダを作成します。
ZIPファイルは不要になったため、
rm inheritance.zip
を実行し、プロンプトで “y “に続いてEnterで応答すると、ダウンロードしたZIPファイルが削除されます。
次に
cd inheritance
の後にEnterを押して、そのディレクトリに移動する(つまり、開く)。これでプロンプトは以下のようになります。
inheritance/ $
すべて成功した場合は、次のように実行します。
ls
すると、inheritance.c というファイルが表示されます。
もし問題が発生した場合は、もう一度同じ手順を踏んで、どこが間違っていたかを確認してください
理解を深める
inheritance.c
の配布コードを見てください。
person という型の定義に注目してください。各 person は2つの親の配列を持ち、それぞれが別の person 構造体へのポインタになります。それぞれの人は2つの対立遺伝子の配列をもち、それぞれがchar ('A'
、'B'
、または'O'
) で表されます。
では、main
関数を見てみましょう。この関数は、乱数生成器を「シード」する (すなわち、いくつかの初期入力を提供する) することから始まります。この乱数生成器を使って、あとでランダムな対立遺伝子を生成します。次に、main
関数は create_family
関数を呼び出して、3世代 (すなわち、本人とその両親、祖父母) の家系に対する person
構造体の作成をシミュレートします。次に print_family
を呼び出して、それぞれの家族とその血液型を出力します。最後に、この関数は free_family
を呼び出して、malloc
で割り当てられていたメモリを解放します。
create_family
関数と free_family
関数の作成があなたの課題です。
実装の詳細
inheritance.c
の実装を完了して、特定の世代サイズの家系を作成し、各家系のメンバーに血液型対立遺伝子を割り当てます。最も古い世代には、ランダムに対立遺伝子が割り当てられます。
create_family
関数は整数 (世代) を入力として受け取り、 (mallocを介して) その世代数の家族の各メンバーに対して1人を割り当て、最も若い世代の人へのポインタを返します。- 例えば、
create_family(3)
は両親が2人いる人へのポインタを返さなければなりません。
- 各個人には対立遺伝子が割り当てられていなければなりません。最も古い世代はランダムに (
random_allele
関数を呼び出すなどして) 対立遺伝子をもち、若い世代はそれぞれの親から (ランダムに) 1つの対立遺伝子を受け継ぐべきです。
- 各自に親を割り当てます。最も古い世代では、両方の親を NULL に設定し、より若い世代では、それぞれが異なる親を指す2つのポインタの配列にする必要があります。
- 例えば、
create_family
関数をいくつかのTODOに分割して完成させましょう。
- まず、新しいユーザーにメモリを割り当てる必要があります。
malloc
を使用してメモリーを割り当て、sizeof(person)
を使用して割り当てるバイト数を取得できることを思い出してください。 - 次に、世代数が1より大きいか
(generations > 1)
どうかをチェックする条件を含めます。generations > 1
ならば、まだ割り当てるべき世代があることになります。create_family
を再帰的に呼び出すことで、すでにparent0
とparent1
という 2 つの新しい親を作成しました。そして、create_family
関数は、あなたが作成した新しいperson
の親ポインタを設定する必要があります。最後に、それぞれの親からランダムに1つの対立遺伝子を選び、新しい人の両方の対立遺伝子を割り当てます。
- そうでない場合 ( generations==1 の場合) 、この個人の親データはありません。両親は両方とも NULL に設定し、それぞれの対立遺伝子はランダムに生成します。
- 最後に、関数は割り当てられた人のポインタを返します。
free_family
関数は、人へのポインタを入力として受け付け、その人のメモリーを解放してから、その人のすべての祖先のメモリーを再帰的に解放します。
- これは再帰関数なので、最初にベースケースを処理する必要があります。関数への入力が NULL の場合、解放するものがないため、関数はすぐに戻ることができます。
- そうでない場合は、子を解放する前に、その人の両方の親を再帰的に解放する必要があります。
ウォークスルー
このビデオは、コースがまだコードを書くためにCS50 IDEを使用していたときに記録されたものです。インターフェイスはあなたのCodespacesと異なるように見えますが、2つの環境の動作はほぼ同じであるはずです
ヒント
rand()
関数は対立遺伝子をランダムに割り当てるのに有用です。この関数は、0
からRAND_MAX
の整数、つまり32767
を戻します。- 特に、0または1の擬似乱数を生成するには、式
rand() % 2
を使用します。
- 特に、0または1の擬似乱数を生成するには、式
- 特定の人にメモリを割り当てるには、
malloc(n)
を使うことができます。この関数は引数としてサイズを取り、nバイトのメモリを割り当てます。 - ポインタを介して変数にアクセスするには、矢印表記を使用できます。
- たとえば、
p
が個人へのポインタである場合、この個人の最初の親へのポインタはp->parents[0]
. によってアクセスできます。
- たとえば、
解決方法がわかりませんか?
コードのテスト方法
./inheritance
の実行時、プログラムは前段で説明されているルールに従う必要があります。子供は両親から1つずつ、2つの対立遺伝子をもつべきです。両親はそれぞれの両親から1つずつ、2つの対立遺伝子をもつべきです。
例えば、以下の例では、0世代の子供は世代1の両親からO対立遺伝子を受け取りました。世代1の片親は片側の祖父母からAを、もう片側の祖父母からOを受け取りました。同様に、もう片側の親は祖父母からOとBを受け取りました。
$ ./inheritance
Child (Generation 0): blood type OO
Parent (Generation 1): blood type AO
Grandparent (Generation 2): blood type OA
Grandparent (Generation 2): blood type BO
Parent (Generation 1): blood type OB
Grandparent (Generation 2): blood type AO
Grandparent (Generation 2): blood type BO
check50
を使用して以下を実行し、コードの正確さを評価してください。ただし、コンパイルとテストは必ず自分で行ってください。
check50 cs50/labs/2022/x/inheritance
以下を実行し、style50
を使用してコードのスタイルを評価します。
style50 inheritance.c
提出方法
次のコマンドを実行し、GitHub のユーザー名とパスワードを入力してログインします。セキュリティのため、パスワードには実際の文字ではなくアスタリスク (*
) が表示されます。
submit50 cs50/labs/2022/x/inheritance