この科目を履修し単位を取得する予定の方は, 講義初回に必ず出席してください.
課題
自己紹介をお願いします.
いま興味のある数学・数理科学(の分野)について自由に答えてください. これまで学んだ内容でも, これから勉強したい内容でも何でも構いません.
文章「1.23+4.56は5.79です」を表示するプログラムを, 書式指定を用いて作成しなさい.
print('%.2f+%.2fは%.2fです' % (1.23,4.56,5.79))
※ 指示桁値がないと「1.230000+4.560000は5.790000です」と表示される(今回はこれも正解とした).
123 を 00000123 と出力するための書式指定を答えなさい.
print('%08d' % (123))
「私の名前は****で, 学修番号は****です」と出力するプログラムを, format メソッドを使って書きなさい. ただし****の部分にはあなたの名前と学修番号が入る. なお使用する変数は好きに決めてよい.
a='横山俊一'
b=19850711
print(f'私の名前は{a}で, 学修番号は{b}です')
第2回 (10/14) 演習の回
※ 詳細は 10/7 の講義中に指示します.
課題
以下のプログラムを実行したとき, a および c の値がどのように変化するか説明し, 最後に print 関数によって表示される値を答えなさい.
a=5
b=7
c=2
a -= b/c
c += b-a%c
a = (c-b)*40*a//c
print(a)
実際に1行ずつ実行して確かめればよい(そのための練習問題). なお答えのみ記したものは大幅減点した.
・4行目: a=5-7/2=1.5, cは変わらず2
・5行目: aは変わらず1.5, c=2+7-(1.5を2で割った余り)=7.5
※ スライドの仮定(int型指定)をみたしていないケースだが, この場合はそのまま1.5が残留する.
・6行目:a=(7.5-7)*40*1.5//7.5=30//7.5=4.0, cは変わらず7.5
よって答えは4.0である. 実際, 30÷7.5の商はきっかり4だが, 30がfloat型なのでこれに影響されている.
演算子が複数含まれている場合, 実行される順番が決まっている. 上記問題 1. における実行順序(優先順位)について簡潔に説明しなさい.
これは通常の演算と同じ. 例えば加減より乗除が優先される, ()の内部を優先するなどである.
// についても除算のカテゴリーなので, / と同じ優先順序である.
以下のプログラムはエラーとなり正しく実行できない. その誤りを指摘し, 正しいプログラムに修正しなさい. なお誤りは1ヶ所とは限らない. また, ここで「正しいプログラム」とは, 最終実行結果が「81」となるプログラムのこととする.
a=2: b=9
b=**a
print(b)
1行目の : が ; であることと, 2行目の =** が **= であることの2点(これは簡単).
真偽判定(True / False)は, 例えば以下のようにプログラムすることができる.
print(not True and False)
上を実行すると False が出力される. 同様のプログラムをいくつか試すことで「and」「or」「not」の実行順序(優先順位)を特定し, その根拠を述べなさい. 特定のために実行したプログラムもすべて含めること.
優先順序は not > and > or の順に高い.
上記からまず「(not True) and False」なら「False and False」の意味になるので, 問題文の通り出力は False になる. 一方「not (True and False)」ならば「not False」, つまり True の意味になるので問題文に反する. したがって先に左から先に not を実行していることになるから not が優先されている.
あとは and と or を比較すればよいが, これは例えば「True or True and False」などとすればよい. これを実行すると True となり, これは「True or (True and False)」を意味するので, and が優先されている.
第4回 (10/28) リストとソート ※ スライドは前回を参照
課題
以下のリストを考える:
L = [43,76,23,11,79,54,23,43]
(a) L を数の大きい方から順に並べ替えるためのプログラムを答えなさい.
L.sort(reverse=True)
(b) (a) で得られた(上書きされた)リスト L に対し, 76 と 54 の間に 61 を挿入するプログラムを答えなさい.
L.insert(2,61)
(c) (b) で得られた(上書きされた)リスト L から 23 をすべて削除するプログラムを答えなさい.
注意:スライドでは remove の例が文字列のリストだったが, 今回は整数なので L.remove(23) のように書く(シングルクォーテーションはつけない).
L.remove(23); L.remove(23)(単純に2回実行する)
実は while 文を使えばよりスマートに書ける(次回以降に扱う)
リストに対して, 含まれる値の最大値・最小値・合計を求める関数 max, min, sum がある. 例えば上のリストで
S = sum(L)
を実行すると 352 と出力される. 以上をもとに, オリジナルのプログラムを作成しなさい. ただし以下の条件をすべてみたすこと:
・関数 max, min, sum をすべて用いること.
・プログラムは10行以上とすること.
・何を計算するプログラムであるかを別途明記すること.
並べ替えを行う関数は sort の他に sorted がある. これは以下のように用いる:
Ls = sorted(L)
この関数は sort とは大きく異なる特徴をもつ. それは何か, 自由に探究してみよ.
ヒント: 前回スライドの最後の注意.
sort 関数は, 問題 1. で扱ったように元々のリストを上書きしている. これに対し, sorted 関数は新しくリストを保持するため, 元々のリストを上書きしていない(そのため print(L.sort()) が None を返すと言及した/対して print(sorted(L)) は有効である). なお sort 関数の操作を「破壊的」(インプレース:in-place), sorted 関数の操作を「非破壊的」(ノットインプレース:not in-place)であるという.
11/4 大学祭期間
課題
0以上100以下の整数を変数 p に代入し, 以下のように表示するプログラムを書きなさい. なお p はキーボードから入力できるようにしても, 最初に適当に代入しておいてもよい.
・p が90以上ならば「あなたの成績はAです」と表示される.
・p が80〜89ならば「あなたの成績はBです」と表示される.
・p が70〜79ならば「あなたの成績はCです」と表示される.
・p が60〜69ならば「あなたの成績はDです」と表示される.
・p が59以下ならば「あなたの成績はFです」と表示される.
ただし, p が0以上100以下をみたさない場合はエラーメッセージを返すこと.
エラーを返す場所は最初でも最後でもよいが, 一般的には最初に置いて reject するほうが書きやすい. 以下その例:
if p<0 or p>100:
print("入力値に誤りがあります")
elif p>=90:
print("あなたの成績はAです")
elif p>=80:
print("あなたの成績はBです")
elif p>=70:
print("あなたの成績はCです")
elif p>=60:
print("あなたの成績はDです")
elif p>=0:
print("あなたの成績はFです")
この記法のポイントは, 最初にエラーの範囲を指定することで or 構文を極力減らしているところにある. もちろん elif パートで if p>=80 and p<90 のように書いても構わない(この書き方の方が多かった).
2つのリスト a=[1,2,3,4,5,6,7], b=[ ] を考える(b は空のリストである). このとき, for 文とリスト a を使って, リスト b を
b=[2,5,10,17,26,37,50]
に上書きしたいとき, 下の ( ? ) にあてはまるプログラムを答えなさい.
for x in a:
b.append( ? )
例えば x^2+1 など.
前問2において, 内包表記とリスト a を使って
b=[2,5,10,17,26,37,50]
に上書きするプログラムを答えなさい.
b=[x^2+1 for x in a]
次のプログラムの実行結果を答え, 関数 continue は何を実行する関数か考察しなさい.
for x in range(5):
if x==3:
continue
print(x)
for ループ文において break したくないとき, 特定の条件下のみ処理をスキップする命令である. 実際, これを実行すると 0,1,2,4 が print され, 3はスキップされている.
第6回 (11/18) 条件分岐:応用編 ※ スライドは前回を参照
課題
以下のように, 100 から7ずつ引き算した 自然数 のみを順に表示させるプログラムを while 文を用いて書きなさい.
100
93
86
...
9
2
例えば以下のように書ける:
n=100
while n>0:
print(n)
n-=7
for, if, while を すべて 使って自作のプログラムを書きなさい. ただし以下の条件をみたすこと:
・プログラムは 20行以上 とする.
・プログラムの中に必ず1ヶ所以上 内包表記 を用いること.
・何を計算するプログラムなのか, その説明を完結に添えること.
力作揃いで楽しく拝見しました (^^)
課題
引数を4つ以上もつ 関数を1つ作成しなさい. 何を計算する関数なのかを明記すること.
力作揃いで興味深く拝見しました (^^)/
5つの整数 a,b,c,d,e が入力されたとき, これらを小さい順に並び替えたリストを返す関数 srt を lambda 関数を用いて 書きなさい.
ヒント: 第4回の課題3で登場した sorted 関数を用いるとよい. その際, lambda 関数では1行で書き切るので, 直接 sorted([a,b,c]) のように書けばよい.
srt=lambda a,b,c,d,e: sorted([a,b,c,d,e])
前問 2. の関数 srt を callback 関数を用いて 定義し, リスト [23,54,76,22,23] の並び替えを実行しなさい.
ヒント: lambda 関数を用いる. より正確には, 例えば以下のように書ける:
def srt(< 1 >,callback):
print(< 2 >)
srt(23,54,76,22,23,< 3 >)
とくに < 3 > は前問 2. と同様のプログラムになるはず.
< 1 > a,b,c,d,e
< 2 > callback(a,b,c,d,e)
< 3 > lambda a,b,c,d,e: sorted([a,b,c,d,e])
第8回 (12/2) 関数:応用編 ※ スライドは前回を参照
課題
以下のような「かけ算九九」を出力する関数 kuku を作成しなさい(引数不要). ただしプログラムの中身は 3行以内 に収めること.
1×1=1
1×2=2
...
9×8=72
9×9=81
※ つまり81行の出力となる.
例えば format メソッドを使えば以下のように書ける:
for i in range(1,10):
for j in range(1,10):
print(f'{i} × {j} = {i*j}')
もちろん通常通り出力させても構わない. range の範囲に注意すること.
いくつかの自然数のリスト numbers が与えられたとき, 奇数 odd_num と偶数 even_num の2つのリストを同時に返す関数 split_numbers を作成しなさい. ただし, 奇数リストは小さい順(昇順)に, 偶数リストは大きい順(降順)で出力すること.
例えば以下のように書ける(sorted 関数と reverse オプションを用いた):
def split_numbers(numbers):
odd_num=sorted([x for x in numbers if x%2!=0])
even_num=sorted([y for y in numbers if x%2==0], reverse=True)
return odd_num, even_num
以下の関数 xxx は何を実行する関数であるか説明し, その活用例を1つ挙げなさい.
def xxx(a,b):
itsc=[]
for e in a:
if e in b and e not in itsc:
itsc.append(e)
return itsc
2つのリスト a,b が与えられたとき, 共通(重複)するもののみを集めたリスト itsc を返す関数である.
第9回 (12/9) 調整回
※ 詳細は kibaco にて指示します.
第10回 (12/16) 数式処理の活用事例:C(Magma)の場合 Part 1
課題 以下はすべて Magma Calculator を用いて計算せよ. ソースコードと実行結果の両方をコピー&ペーストして提出すること.
30桁以上の自然数を1つ選び, 素因数分解を行いなさい.
Factorization(ここに自然数を入力);
自然数の積 402×409×416×・・・×493×500 を計算するプログラムを書き, 実行しなさい. ただし, 計算式をすべてベタ打ちで記述してはいけない(Magma の内部関数を用いて計算せよという意味).
例えば &*[7*n+3: n in[57..71]]; や &*[402+7*n: n in [0..14]]; のように初項・末項を直接指定してもよいし, 現れる自然数が7で割ると3余ることを用いて &*[n: n in [402..500] | n mod 7 eq 3]; のように書くこともできる(後半で条件をつけている). 何れにせよ答えは 6279739080859050124454951342776934400000 である.
不定方程式 x+26*y^2+91*z^4=894964220 をみたすような自然数 (x,y,z) の組を1つ見つけなさい. ただし x^n はxのn乗(べき乗)を表す.
exists(x,y,z){<x,y,z> : x,y,z in [1..100] | x+26*y^2+91*z^4 eq 894964220}; x; y; z; を実行すればよい. x, y, z の範囲を適切に広げるところがポイント. 答えは例えば x=98, y=31, z=56 となる.
講義ビデオで登場した内部関数をいくつか組み合わせて, 自作のプログラムを作成しなさい. その際, 何を計算するプログラムかを明記すること.
自由解答. よくできていました.
第11回 (12/23) 数式処理の活用事例:C(Magma)の場合 Part 2
課題 以下はすべて Magma Calculator を用いて計算せよ. ソースコードと実行結果の両方をコピー&ペーストして提出すること.
自作の関数を1つ作成しなさい. ただしデモンストレーションで扱った例とは異なるものとし, 何を計算するための関数なのかを明記すること.
自由解答. よくできていました.
18238938091^217391298317 mod 2713897892 を計算しなさい. なおこのまま実行すると入力上限値オーバーでエラーを返すことに注意せよ. 例えば Magma でのオーバーフロー例は以下の通りである:
18238938091^217391298317 mod 2713897892;
>> 18238938091^217391298317 mod 2713897892;
^
Runtime error in '^': Argument 2 is too large
先に乗算をしてから mod するのではなく, 18238938091 を1回かけるたびに mod して更新すれば桁溢れを防ぐことができる.
別紙の問題 に解答しなさい.
例えば以下のように書ける:
BNZagier:=function(k)
h:=0; s:=1; c:=k+1;
for n in [2..k+1] do
c:=c*(n-k-2)/n;
h:=h+c*s/n;
s:=s+n^k;
end for;
return h;
end function;
数千番目オーダーのベルヌーイ数であれば, 内部関数に比べておよそ50倍前後高速化される. 組み合わせのパートは Binomial 関数を用いず, 事前に計算して実装している.
出典は D. Zagier, A modified Bernoulli number (9pp).
12/30 冬季休業期間
第12回 (1/6) 演習の回
※ 詳細は 12/23 の講義中に指示します.
第13回 (1/13) 総括・最終レポート課題 【提出期限: 2/1(日)23:59 厳守】
最終レポート課題 以下の5題から 2題以上 を選択し解答しなさい. 中には多少難しい問題も含まれており, 講義で述べた内容だけでは解けないものもある. 適宜参考書などを活用して取り組むこと(解けなくてもあまり気にする必要はない).
解答は原則として kibaco のテキストボックスに書き込んで提出とするが, 必要に応じて添付ファイルを作成して構わない. メイル等や紙媒体での提出は受け付けない.
Python 以外のプログラミング言語を1つ選び「Python と全く同じ計算を行っていながら, Python よりも高速に計算が可能な例」を1つ作りなさい. 両者のソースコード・出力結果・ベンチマークに用いたコンパイラや技法等を必要に応じて明記し, 採点者(横山)が再現可能なデータを提供すること.
3つの整数 a,b,c を用意する. a,b,c に2以上の自然数が入力されたとき, a,b,c が互いに素(最大公約数が1)であるかどうかを判定するプログラムを作成しなさい. 互いに素でない場合は, その最大公約数も出力できるように組むこと. a,b,c はあらかじめ適当な値を代入しておいてもよいし, 入力を受け付ける形にしておいてもよい.
5つの整数 a,b,c,d,e を用意する. a,b,c,d,e に整数が入力されたとき, その中間値(つまり重複込みで3番目に大きい or 小さい)を出力するプログラムを作成しなさい. 例えば 3,7,5,9,5 ならば中間値は5である. a,b,c,d,e はあらかじめ適当な値を代入しておいてもよいし, 入力を受け付ける形にしておいてもよい.
2年後(2028年)はうるう年である. 自然数 N が与えられたとき, 西暦 N 年がうるう年であるかを判定するプログラムを書きなさい. ただし 条件分岐 if は1回のみ使用可 とする. つまり
if *****
*****
elif ***
というプログラムは if が2回使われているので不適という意味である. うるう年の定義は以下の通りとする:
・西暦が4で割り切れる年はうるう年である.
・ただし, 西暦が100で割り切れる年はうるう年ではない.
・ただし, 西暦が400で割りきれる年はうるう年である.
西暦・月・日を合計8桁の整数で表したものが素数であるとき, その日(整数)を 素数日 prime day とよぶことにする. 例えば2020年最後の素数日は 20201231(大晦日)であり, 2021年最初の素数日は 20210101(元日)である. このように素数日どうしが隣り合う(素数日の翌日も素数日となる)とき, 両者を 連続素数日 twin prime day とよぶことにする. なおその次の連続素数日は 20280229 と 20280301 である.
このとき, 2026年1月1日から2099年12月31日までの間に訪れる, すべての連続素数日を列挙するプログラムを書きなさい. ただし:
・20260101 および 20991231 が素数日でないことは既知としてよい.
・各月の日数は以下の通りとする:1月・3月・5月・7月・8月・10月・12月は31日まで, 4月・6月・9月・11月は30日まで, 2月はうるう年のとき29日まで, それ以外は28日まで.
第14回 (1/20) 最終レポート作成・質問対応回 Part 1
※ 詳細は 1/13 の講義中に指示します.
第15回 (1/27) 最終レポート作成・質問対応回 Part 2
※ 詳細は 1/13 の講義中に指示します.
Contact: s-yokoyama [at] tmu.ac.jp