プログラミング入門I
2024.11.25
for 文

Back to index page



  1. 本日の作業内容

  2. 前回の確認テストについて

    予想していたことですが,タイムプレッシャーがかかるテストではエラー続発でした.ただ,エラーの中には,きちんとした処理を書いていながらも途中で時間切れになっているものも見られましたので,それらについては多少部分点をつけています.単純な文法間違いや記述間違いはやはり0点としています.

    全体としては2つのスイッチに状態がそれぞれ2つあるので,条件は4つに分かれるという基本的なことが処理の中で実現されていないものが多くみられました.論理的にきちんと考えてから処理を書くようにしないといけません.

    それと変数名の先頭に大文字を使う人が多くなってきました.変数名は小文字で始めるというマナーを今一度思い出してください.

    実行時エラー: b2404 b2407 b2409 b2410 b2415 b2423 b2432 b2437 b2443 b2455 b2458 b2465

    前回の宿題提出: b2435

    ヘッダ部分の番号間違い: b2416

    出力時番号間違い: c02

    ハイフンラインなし: b2416

    以下は例によって問題のあるプログラムの例です.参考にしてください.

    
    

    ("#################################")
    ("#")
    ("# プログラミング入門Ⅰ 宿題 2024,11,11")
    ("# 学生番号: s246058")
    ("# 氏名: 安田 清兵衛")
    ("#")
    ("#################################")
    

    だ~か~ら~,ヘッダいじるのやめろって言ってるだろうが!どうしてダウンロードしないの?

    if num1 = 1:
        print('s1: ON')
    else num1 = 2:
        print('s1: OFF')
    

    やりがちな間違いの例としてWebテキストで紹介していたものですね.他の言語ではエラーではなく間違った処理になるのですが,Python ではエラーメッセージで教えてくれます.さらには else 節は当然ですが条件式を書きません.それ以外なんだから,条件はもう付けません.

    if S1 == 0:
        if S2 == 0:
            Light == ON
    

    上のこちらもエラーになった例です.代入に比較演算子の == を使ってしまったのでエラーです.さらに,文字列を代入したいのなら,引用符が必要です.

    if s1 == 1:
        s1 = ON
    else:
        s1 = OFF
    
    if s2 == 1:
        s2 = ON
    else:
        s2 = OFF
    if s1 == 1:
        if s1 == s2:
            Light = ON
    else:
        Light = OFF
    

    こちらも同様に文字列を指定する引用符を忘れているので,エラーになっています.基本中の基本なんですが,まだ身についていないということでしょうかね.

    if s1 == 1:
        print('S1: ON')
        elif s1 == 0:
            print('S2: OFF')
    if s2 == 1:
        print('S2: ON')
        elif s2 == 0:
            print('S2: OFF')
    

    上のものもエラーの例です.if に対する elif は同じ階層のインデントでなければいけないのですが,if 節の中にインデントされてはいっているので,elif の前提となる if が無いというエラー場出たはずです.しかも,今回は if が偽になった場合は1通りしかないので,elif ではなく,else が適切です.

    num1=random.randint(0,9)
    if 0 <= num1 <= 4:
        print(f'S1: ON')
    else:
        print(f'S1: OFF')
    

    1/2 の確率で2つの乱数を発生させるのに,このような面倒な処理は不要です.

    num1 = random.random()
    num2 = random.random()
    

    こちらもたかが2通りの乱数を用意するだけなのに,実数の乱数は要らないです.

    if S1 == 0:
        print(f'S1: ON')
    elif S1 == 1:
         print(f'S1: OFF')
    

    先ほどの例にもありましたが,elif ではなく else を使用すべきです.

    if S1 == 1 and S2 == 1:
        print(f"S1: ON S2: ON Light: ON")
    else:
        print(f"S1: ON S2: OFF Light: OFF")
    

    場合は4通りあるのに,2つに集約してしまっているので,結果がおかしくなります.つまり,スイッチが OFF ON と OFF OFF の場合がありません.

    if swich1 == swich2 == 1:
        print("S1: ON")
        print("S2: ON")
        print("Light: ON")
    elif swich1==1 and swich2==2 :
        print("S1: ON")
        print("S2: OFF")
        print("Light: oFF")
    elif swich1==2 and swich2==1 :
        print("S1: OFF")
        print("S2: ON")
        print("Light: oFF")
    

    今回上のような処理が何例か見られました.3行分の表示をまとめて実行しようとしているので,処理が複雑になるし,文字数が無駄に増えます.さらに,途中で時間がなくなったのか,最後の else が無いですね.綴りも間違っていますし.

    num1=random.randint(1,2)//2
    num2=random.randint(1,2)//2
    if num1==1 and num2==1:
        print(f'S1:ON')
        print(f'S2:ON')
        print(f'Light:ON')
    elif num1==1 and num2==0:
        print(f'S1:ON')
        print(f'S2:OFF')
        print(f'Light:OFF')
    elif num1==0 and num2==1:
        print(f'S1:OFF')
        print(f'S2:ON')
        print(f'Light:OFF')
    elif num1==0 and num2==0:
        print(f'S1:OFF')
        print(f'S2:OFF')
        print(f'Light:OFF')
    

    こちらも3行分まとめて条件分岐させようとしているので複雑になっていますが,その前にまずよくわからないことをしています.1もしくは2を発生させたのに,それを0と1に変えていますが,だったら最初から0と1を作れば良さそうなものです.さらに最後が else になっていないですね.

    if num1==1:
        num3=('ON')
    if num1==2:
        num3=('OFF')
    if num2==1:
        num4=('ON')
    if num2==2:
        num4=('OFF')
    if num1==num2==1:
        num5=('ON')
    else: num5=('OFF')
    

    if に対して偽の場合も用意するのなら else を使うと説明したはずですが,if の連発になっています.あと,変数名についても今回 num がふさわしいでしょうか.代入するのは文字列ですが?カッコも不要ですし.

    if num1 == 0:
        print('S1: ON')
        if num2 == 0:
            print('S2: ON')
            print('Light: ON')
        else:
            print('S2: OFF')
            print('Light: OFF')
    elif num1 == 1:
        print('S1: OFF')
        if num2 == 0:
            print('S2: ON')
            print('Light: OFF')
    else:
         print('S2: OFF')
         print('Light: OFF')
    

    上のものは複雑な処理になってしまって,結局間違った分岐となってしまっています.まず,elif が使われているところですが,これまで何度か指摘しているようにこれは else がふさわしいです.ただ,elif となっているものの,もうnum1 の値は1以外には無いので,最後の else に進むことは決してありません.そのため,全ての条件を満たす処理にはなっておらず,以下のように抜けが生じます.

    Student number: s******
    
    S1: OFF
    
    ------------------------
    

    if num1 == 1 and num2 == 0:
        print('S1: ON')
        print('S2: OFF')
        print('Light: OFF')
    
    elif num1 == 0 and num2 == 1:
        print('S1: OFF')
        print('S2: ON')
        print('Light: OFF')
    
    else :
        print('S1: ON')
        print('S2: ON')
        print('Light: ON')
    

    分岐が3つしか無いということは当然正しくないのですが,変数 num1 と num2 の両方が0でも点灯してしまうことになっています.

    if num1==1 and num2==1:
        print('S1:ON')
        print('S2:ON')
        print('Light:ON')
    
    else:
         print('S1:OFF')
         print('S2:OFF')
         print('Light:OFF')
    

    今度は両方ONか両方OFFしかなくなっています.

    S1=random.randint(1,2)
    S2=random.randint(1,2)
    if S1==S2==1:
        result='ON'
    elif S1==S2==2:
        result='ON'
    else:
        result='OFF'
    
    print(f'S1:{S1}')
    print(f'S2:{S2}')
    print(f'Light:{result}')
    

    最後の上のものも場合分けがおかしいですね.2つの変数が一致したらとにかくONというのはおかしいですし,最後の print のところの f 文字列では数値を出力しようとしています.

  3. 前回の宿題について

    反復処理が始まっていきなり無限ループが出てきました.自分でも無限ループであることはわかるはずなので,解決してから出すか,出すのをあきらめるかのどちらかにしてください.部分点も何もつきません.

    無限ループ: b2406

    以下は例によって問題のあるプログラムの例です.参考にしてください.

    i=0
    while i <= 999:
        num1=random.randint(100,999)
        if i < num1:
            i=num1
            print(num1,end = ' ')
    else:
        print()
    

    上のものが無限ループの例ですが,while 文の条件式で変数 i が999以下が真で書いています.発生する乱数の最大値は次の行にあるように999ですから,条件式は必ず真fになります.そのため,次の if 文の条件式が偽になって何も表示しなくなっても,ループは実行されづ付けます.

    Number1=random.randint(100,999)
    

    変数名は小文字で始めること.

    import random
    
    print('Student number: s246047')
    
    num1 = random.randint(100, 999)  
    print(num1, end=" ")  
    
    while num1 < 999:
        num2 = random.randint(num1 + 1, 999)
        print(num2, end=" ")  
        if num2 == 999:
            break 
        num1 = num2
    else:
        print()
    

    前にも言及したことがありますが,学生番号を出力した後の下からある print('') を消さないこと.

    while num<999:
        import random
        num=random.randint(num+1,999)
        print(num,end=' ')
    

    while 文の中で何度も import してしまっています.冒頭で一回 import すれば十分ですね.

    num1=random.randint(100,999)
    while num1 < 999:
        num2=random.randint(num1+1,999)
        print(num1,end=' ')
        num1=num2
    
        
    else:
        print(f'999')
    

    今回多く見られたのが上のように変数を2つ使用するものです.乱数を格納する変数は1個で十分なので,不要な変数は作らないようにしましょう.また,最後 else 節で出力する数を 999 で決め打ちしていますが,そこも変数にしておくと,汎用性が高まるのでその方が望ましいです.

    num1=random.randint(100,999)
    print(num1,end=' ')
    while num1 != 999:
        num2=random.randint(num1+1,999)
        print(num2,end=' ')
        num1=num2
    
        print('\n------------------------\n')
    

    最後にハイフンラインを出力する print 文がインデントされてしまっています.そうなると,while 文のスイートになってしまうので,反復して出力されることになり,以下のようになってしまいます.自分で気づくはずですので,何とかしてください.

    141 956 
    ------------------------
    
    978 
    ------------------------
    
    981 
    ------------------------
    
    994 
    ------------------------
    
    999 
    ------------------------
    

    num1= random.randint(100, 999)
    print(f'{num1}')
    
    while num1<999 :
        num2=random.randint(num1+1,999)
        print(num2, end=' ')
        num1=num2
    else :
        print()
    

    num1 を出力する print 文が最後改行しているので,以下のような表示になってしまいます.これも自分で気づくはずなので,何とかしてから出してください.

    816
    977 992 995 997 999 
    

    num1=0
    while num1<999:
        num2=random.randint(100,999)
        if num2==999 :
            print('999')
            break
        elif num1
    

    今回上のように条件分岐を使用している人が結構多くみられました.この程度のプログラムでは実感することはありませんが,プログラムの処理で時間がかかるのは条件分岐です. while 文を使用していることですでに条件分岐は使用しているので,それに追加で無駄な条件をつけるのはやめましょう.一度 if 文を学習してしまうと,何でもかんでも if で処理したがる人が必ずいるのですが,if 無しで実現できるなら,そちらを選択してください.

    i = 100
    
    while i < 999:
        num = random.randint(i+1,999)
        print(num, end = ' ')
        i = num
    
    
    else:
        print('')
    

    これでは乱数の値として100が出力されることがありません.3桁の整数という指定の十分条件を満たしていません.

    while num1<999:
        num2=random.randint(1,100)
        print(num1,end=' ')
        num1=min(num1+num2,999)
    else:
        print(num1)
    

    999よりも大きくなってしまったら999の方を選択するという処理ですので,乱数として999を出しているわけではありません.題意を満たしていないと判断します.

    numbers = []
    current_number = 100
    
    while current_number < 999:
        current_number = random.randint(current_number +1, 999)
        numbers.append(current_number)
        
    print(numbers)
    

    どうしてこの程度の課題でリストが必要になるのでしょうかね?使ってもいいですが,リストを使いこなすほど Python に習熟しているのなら,リストを使わない方法も容易に実現できるはずですし,下のような出力結果ではなく,実施例と同じ出し方を知っているはずです.

    [449, 942, 967, 983, 993, 999]
    

    if num1!=999:
        while num1<999:
            num2=random.randint(num1+1,999)
            print(num2)
            num1=num2
    

    ただ単に print で変数の値を出力したら必ず改行もくっついてくるので,以下のように表示されることはわかっているはずですよね.直してから出してください.

    175
    741
    960
    990
    997
    998
    999
    

    num = 100
    while num < 999:
        ran_num = random.randint(1,99)
        sub = num + ran_num
        print(f'{sub}', end = ' ')
    
        if sub > 999:
            print('')
                
        else:
            num = sub
    

    if で条件が真のときだけ num = sub を実行するので,変数 sub が999を超えた値のときでも変数num は999未満で while 文の条件式は真のままです.なので,たまたま運よく999になったときにしかループから抜け出すことができません.そのため,実行結果は例えば以下のようになってしまいます.

    124 190 279 338 353 359 439 486 545 567 640 644 692 769 780 859 905 956 1001 
    994 1031 
    1035 
    1055 
    1055 
    1045 
    1010 
    1017 
    1040 
    1080 
    1071 
    1009 
    1083 
    1024 
    1075 
    1027 
    1006 
    1040 
    998 1004 
    1008 
    1005 
    1053 
    1060 
    1017 
    1069 
    1001 
    1046 
    1075 
    1087 
    1010 
    1085 
    1048 
    1037 
    1006 
    1066 
    1072 
    1040 
    1094 
    1057 
    1034 
    1033 
    1060 
    1035 
    1024 
    1006 
    1072 
    1005 
    1015 
    1082 
    1062 
    1040 
    1044 
    1094 
    1017 
    1080 
    1056 
    1068 
    1037 
    1005 
    1061 
    1030 
    1035 
    1046 
    1047 
    1042 
    1045 
    1007 
    1019 
    1009 
    1082 
    1082 
    1092 
    1052 
    1046 
    1001 
    1005 
    1001 
    1096 
    1023 
    1044 
    1076 
    1081 
    1008 
    1045 
    1029 
    1095 
    1065 
    1050 
    1097 
    1084 
    1076 
    1034 
    1009 
    1097 
    1043 
    1026 
    1043 
    1061 
    1058 
    1006 
    1004 
    1059 
    1056 
    1005 
    1006 
    1071 
    1010 
    1030 
    1049 
    1038 
    1060 
    1040 
    1043 
    1089 
    1060 
    1096 
    1043 
    1092 
    1013 
    1012 
    1063 
    1057 
    1066 
    999 
    

    あなたのせいで,この授業を受ける人はみんな長い縦スクロールをしないとテキストが見れません.迷惑ですよね.変な結果になっているものを提出しないで,ちゃんと直してから出してください.

    i = random.randint(100, 999)
    
    while i < 999:
        num = random.randint(i, 998)
        i = num + 1
        
        print(i,end=' ')
        
    else:
        print()
    

    最初にいきなり変数 i の値が999になってしまうと,何も出力されずプログラムが終わります.

    while True:
        number = random.randint(100, 999)
        print(number)
        if number == 999:
            break
    

    上の例もひどいもので,無限ループにしておいて,乱数の値として999が出たら終わるというものです.なので,何百個も乱数を出して表示し続けます.ダメです.

    さて,以下に示すプログラムですが,どうも困ったもののようです.これだけの文字数のテキストが完全に一致するという現象はそうそうないものです.どういうことなんでしょうかね?

    num1=0
    while num1<999:
        num2=random.randint(100,999)
        if num2==999 :
            print('999')
            break
        elif num1<num2 :
            print(f'{num2}' ,end =' ')
            num1=num2
        else :
            continue
    
    num1 = 0
    while num1 < 999:
        num2 = random.randint(100, 999)
        if num2 == 999:
            print('999')
            break
        elif num1 < num2:
            print(f'{num2}' ,end =' ')
            num1=num2
        else:
            continue
    
    ある人のソース 別の人のソース

    def generate_random_numbers():
        numbers = []
        current = random.randint(100, 999)
        numbers.append(current)
    
        while current != 999:
            next_number = random.randint(current + 1, 999)
            numbers.append(next_number)
            current = next_number
    
        return numbers
    result = generate_random_numbers()
    print("", ", ".join(map(str, result)))
    
    def generate_random_numbers():
        numbers = []  
        current = random.randint(100, 999)  
        numbers.append(current)
    
        while current != 999:
            next_number = random.randint(current + 1, 999)
            numbers.append(next_number)
            current = next_number
    
        return numbers
    result = generate_random_numbers()
    print("", ", ".join(map(str, result)))
    
    ある人のソース 別の人のソース

    成績評価に用いる材料(答案,レポート等)に不正行為があった場合にはその期の単位がすべて無効になるという規定があります.そのことは一応皆さん周知されているはずです.それでもこのような行為が行われているとしたら,確信犯ということで学部に相談させていただくことになります.

    今回はとりあえず0点ということで進めますが,次は無いのでちゃんと自分でやりましょう.

  4. 前回の復習

    前回は while 文について学習しました.何らかの変数の値が条件式が真の間,指示した処理が実行される,という構成でした.条件式に入る変数は,ループが始まる前に値が定義されていないといけないこと,また,反復して処理するスイートの中に,その変数の増分や変更などが含まれていないと無限ループとなってしまうことに注意してください.

  5. for 文

    for 文は基本的には繰り返す回数が決まっているときに使用する反復処理です.もちろん変数の値の回数繰り返すとすると,決まった回数ではないように見えますが,それでもその変数分の回数繰り返すということは,あらかじめ決まっていることになります.

    1. 基本形
    2. 教科書にもあるように,for 文は以下のような基本的な構成となります.

      for 変数 in 並び式:
          スイート
      

    3. range 関数
    4. for 文において,繰り返す回数を指定するのには range 関数が使用されます.引数仕様は以下の通りです.

      range(n)0 以上 n 未満の数値を順番に列挙した数列
      range(a, b)a 以上 b 未満の数値を順番に列挙した数列
      range(a, b, step)a から b の手前までの数値を step 個おきに列挙した数列

      range 関数のツボ

      最初のうちによく間違えることがあるのですが,range(1, 10) のようにしたときには,変数の値が 1 から 9 まで変わる間反復処理を行うので,1 から 10 までとしたいときには,range(1, 11) としないといけません.ここは要注意です.

    5. 動作の確認
    6. 自分で作ったプログラムが思ったように動かないときには,変数の値が反復処理によりどのように変わっていくのかを,逐次手作業で確認してみてください.処理の流れに従って変数が変わっていきますが,それが希望した動作になっているのか,メモなどを取りながら値の変化を確認することが,プログラムの間違いを見つける大事な方法です.

  6. 演習

    今回の演習問題です.

  7. 本日のまとめ

  8. 宿題

    宿題が公開されるのは明日火曜日10:00の予定で,締切りは来週の月曜日12月2日の10:00です.レポート提出システムを使用します.

  9. 次回の予習範囲

    次回も引き続き教科書のp.102-114の範囲を学習しますので,予習をしてきてください.


目次ページに戻る