プログラミング入門I
2023.12.18
多重ループ

Back to index page



  1. 本日の作業内容

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

    テストはプレッシャーがかかる上,前回の演習問題の解答例などを確認していないことも加わってエラーのプログラムが結構出てしまいました.次回以降は注意しましょう.

    実行時エラー: b2316 b2320 b2345 b2349 b2352 b2353 b2354 prog2

    無限ループ: b2360

    末尾ハイフンラインなし: b2349

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

    # #############################
    #
    # プログラミング入門I 確認テスト 2023.12.11
    # 学生番号:  s236099
    # 氏名:     松江 花子
    #
    # #############################
    
    import random
    
    print('Student number: s236099')
    print('')
    
    
    
    
    
    print('\n------------------------\n')
    

    学生番号と名前くらいは自分のものにしませんか?

    maxnum = 0
    minnum = 0
    

    今回実にたくさん見られたのが上のように最小値の初期値を 0 にしたものです.これでは最小値は更新されませんが?

    最大値用の変数の初期値を 0 とするのは,どんな小さな値の乱数が出てきてもまずは更新され,次にそれよりも大きい値が来たらまた更新する,というフローです.ですので,最小値の初期値としては,どんな大きな値がでてもまずはそれで更新され,以後はより小さい値で更新していく,という動作のために大きな値を選択しないといけません.

        if maxnum < num1:
            maxnum = num1
        elif minnum > num1:
            minnum = num1
    

    こちらも実にたくさん見られたものです.最大値と最小値は連動しているということでしょうか?なぜ elif になるんでしょうか?よく考えてください.で,このような書き方だと,下のような結果になってしまうことがあります.

    6 61 60 81 36 13 88 79 36 46 
    the minimum and the maximum numbers among above: 13, 88
    

    上の例ですが,最初の数値はどんなに小さくても,最大値の初期値よりは大きいので最大値が上書きされます.なので,最小値の方には代入されません.そこで,最小値の値が違うものになってしまうことがあります.

    for n in range(10):
        n = random.randint(1, 100)
    

    for 文の変数として使っている n がなぜスイートの中で乱数として扱われるのでしょうか?

    b = 0
    c = 0
    for _ in range(10):
        a = random.randint(1, 100)
        print(f'{a}', end = ' ')
        if a > b:
            b = a
        else:
            c = a
    

    else だからダメなのですが,それにしても世の中には最大値か最小値しか無いのか?

    for _ in range(9):
        num = random.randint(1,100)
        print(f'{num} ', end = '')
        if maxnum < num:
            maxnum = num
        elif minnum > num:
            minnum = num
        else:
            print()
    

    もともと elif があってよくない処理なのですが,さらにおまけの else で改行があるので,結果として以下のように表示してしまいます.

    74 32 74 
    6 79 43 
    29 
    95 91 
    

    for _ in range(10):
        num = random.randint(1, 100)
        print(f'{num} ', end = '')
        num1 = max
        num2 = min
    
    print(f'\nThe minimum and the maximum numbers among above: {num2}, {num1}')
    

    あらかじめ Python に組み込まれている関数の max や min を使っているので,以下のような結果になりました.予約語として何があるのかを全て把握することは難しいかもしれませんが,代表的なものは覚えておきましょう.

    8 50 72 23 56 77 80 44 24 37 
    The minimum and the maximum numbers among above: <built-in function min>, <built-in function max>
    

    エディタで例えば max と入力すると文字の色が変わります.そうなると,それは予約語なので,そのままの使用は避けるべきです.

        print(f"{random.randint(1,100)}end=''")
    

    " " で囲う文字列の範囲が間違っているので,結果は以下のように.

    47end=''
    9end=''
    95end=''
    13end=''
    42end=''
    90end=''
    3end=''
    48end=''
    23end=''
    17end=''
    

    num=random.randint(1,100)
    maxnum=1
    minnum=100
    
    for _ in range(10):
        print(f'{num} ',end= '')
    if num > maxnum:
           num=maxnum
           print()
    if num < minnum:
           num=minnum
           print()
           print(f'The minimum and the maxmum numbers among above:{minnum},{maxnum}')
    

    乱数を for 文の外で発生させているので,表示される変数は1個だけだし, if も for 文の外なので,最後に1回実行するだし.

    34 34 34 34 34 34 34 34 34 34 
    
    The minimum and the maxmum numbers among above:100,1
    

    for _ in range(10):
        num1=random.randint(1,100)
        print(f'{num1}', end=' ')
    
        if num1 > maxnum:
            maxnum = num1
        print(f'The minimum and the maximum numbers among above: {maxnum}')
    

    過年度生のクラスだけで見られた異常な現象.これが次々と出てきました.なんで print 関数を for 文の中に入れるんですかね?

    44 The minimum and the maximum numbers among above: 44
    53 The minimum and the maximum numbers among above: 53
    21 The minimum and the maximum numbers among above: 53
    79 The minimum and the maximum numbers among above: 79
    57 The minimum and the maximum numbers among above: 79
    32 The minimum and the maximum numbers among above: 79
    13 The minimum and the maximum numbers among above: 79
    94 The minimum and the maximum numbers among above: 94
    33 The minimum and the maximum numbers among above: 94
    96 The minimum and the maximum numbers among above: 96
    

  3. 前回の宿題について

    今回はだいたいできていたように思いますが,このところ理解度の格差がどんどん大きくなってきているようです.できる人とできない人が完全に分かれてきています.課題ができていない人は演習の際にもっと質問をするなど,何らかの行動をお願いします.また,各回の演習問題をちゃんと理解してください.解答例もつけていますので,参考にしてください.今回の問題で言えば,前回の演習問題の v. が参考になります.

    で,今回はエラーが1件ありました.プログラミングに関することではなく,ただのテキストファイルを提出しています.どういうことか,わかりませんが,提出の際にはきちんと確認しましょう.

    エラー: b2306 (課題Webページの実行結果の画面を提出)

    出力時番号間違い: b2162

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

    print(f'Point P[{x}, {y}]')
    

    点の座標を表記する際に使用するのはカギカッコ [ ] でしたか?

    print(f'Point P{x} , {y}')
    

    こちらも点の座標の表示が下のように変ですね.

    Point P3 , 3
    

    print('0+------------ x')
    print(' 0 1 2 3 4 5 6')
    

    上のようなものがある程度出てくるとは思っていましたが,案外少なくてそれはそれで安心しました.反復処理を活用してください.過年度生のクラスのほうでこのようなものが多かったので,残念です.

    for i in range(6,0,-1):
            print(f'{i}| ', end = '')
            for j in range(1):
                    if y == i:
                            print(f'  '*(x - 1), end = '')
                            print('*')
                    else:
                            print()
    

    上のプログラムは間違っていません.ただ,インデントが TAB 2個分になっているようで,そうするとプログラムが横に無駄に長くなるので,ちょっと見づらいものになってしまいます.通常の空白文字4個分のTABで十分です.

    さて,以下に示すものは,表示がちょっと違っているもののいくつかの例ですが,実際に自分で見て確認できたはずなので,次回以降は問題があったら直してから提出するようにしましょう.

    for i in range(6, -1, -1):
        if i == 0:
            print(f'{i}+',end='')
        elif i > 0:
            print(f'{i}|', end='')
        for j in range(0, 7):
             if j == x and i == y:
                print(' *', end='')
             elif i == 0:
                 if j == 6:
                     print(' x',end='')
                 else:
                     print('--',end='')
             else:
                print(' ', end='')
    
        print()
    

    微妙なところなんですが,内側の for 文の変数 j の開始が本来は 1 からなのに 0 から始めているので,余分にスペースが入り,下の結果のように * が右にずれています.

    Point P(1,5)
     y
    6|       
    5|  *     
    4|       
    3|       
    2|       
    1|       
    0+------------ x
     0 1 2 3 4 5 6 
    

    for i in range(6, 0, -1):
        print(f'{i}|', end='')
        for j in range(0,13):
            if j == n1 and i == n2:
                print('*', end='')
            else:
                print(' ', end='')
        print()
    

    今度は print 関数の中で x 座標を示す数字が2文字分の幅があることに対応していないために, * が左にずれています.print の中は '*' とかではなく, ' *' のようにスペースを1個入れる必要があります.

    P(3,2)
     y
    6|             
    5|             
    4|             
    3|             
    2|   *         
    1|             
    0+------------ x
     0 1 2 3 4 5 6 
    

    for i in range(6,-2,-1):
        if i == 0:
            print(f'{i}+', end = '')
        elif i > 0:
            print(f'{i}|',end = '')
        for j in range(0,7):
            if (i,j+1) == (numx,numy):
                print(' *', end = '')
            elif i == 0:
                if j == 6:
                    print(' x', end = '')
                else:
                    print('--', end = '')
            elif i == -1:
                print(f' {j}', end = '')
            else:
                print('  ', end = '')
                
        print()
    

    座標の xy が逆ですね.

    Point P(5,4)
     y
    6|              
    5|       *      
    4|              
    3|              
    2|              
    1|              
    0+------------ x
     0 1 2 3 4 5 6
    

    for i in range(0,7):
        print(f'{6 - i}',end='')
        if (6 - i) != 0:
            print('|',end='')
            if (6 - i) == y:
                print('*')
            else:
                print()
        else:
            print('+',end='')
            for _ in range(12):
                print('-',end='')
            print(' x')
    

    y 座標の数値があっているかだけで判定しているので,下のようになってしまいます.

    Point P(5,4)
     y
    6|
    5|
    4|*
    3|
    2|
    1|
    0+------------ x
     0 1 2 3 4 5 6
    

    for y in range(6,-1,-1):
       print(f'{y:>2}',end='')
    
       if num2 == y:
          print('*',end = '')
       else :
          print(' ',end='')
       for x in range(1,7):
           print(f'{x:>2}',end='')
           if num1 == x:
              print('*',end='')
           else :
              print(' ',end='')
       else:
           print()
    

    こちらも似たようなものですが,x 座標の値が一致すれば全部表示となっているので,下のようになります.また,数字は不要ですね.

    Point P(1,2)
     y
     6  1* 2  3  4  5  6 
     5  1* 2  3  4  5  6 
     4  1* 2  3  4  5  6 
     3  1* 2  3  4  5  6 
     2* 1* 2  3  4  5  6 
     1  1* 2  3  4  5  6 
     0  1* 2  3  4  5  6 
    

    for i in range(0,8):
        num3=6-i
        if num3 < 0:
            print(' ', end='')
        else:
            print(f'{num3}', end='')
        for j in range(13):
            if i==7 and j==0:
                print('0', end='')
            elif i==7 and j%2==0:
                print(f'{j//2}', end='')
            elif num3==num2 and j==num1*2:
                print('*', end='')
            elif j==0 and num3==0:
                print('+', end='')    
            elif  j==0:
                print('|', end='')
            elif num3==0 and j==12:
                print('- x', end='')    
            elif num3==0:
                print('-', end='')
            else:
                print(' ', end='')
        else:
            print()
    

    さて,最後に紹介するのは,これまで何度か説明してきたことではあるのですが,余分な変数についてです.上のプログラムで,変数 num3 は for 文の変数 i から作られていますので,不要です.変数 i をきちんと使うことで,このような面倒なプログラムにならずに済むはずです.解答例を参考にしてください.

  4. 前回の復習

    2 重の for 文を中心に多重のループについて学習しました.前回も説明しましたが,画面に文字列を2次元的に表現するグラフや表などで重宝されるのが2重のループです.外側のループの変数が行を下に進める処理に対応し,内側の変数は各行を右に進める処理に対応しますので,それを理解した上でいろいろと考えていきましょう.

  5. 多重ループ

    今回も多重の反復処理です.今回は2次元的な表現だけでなく,数値を扱う際に2重のループが必要になるものもいくつか用意しました.引き続き演習問題を通して多重ループを学習していきましょう.

  6. 演習

    今回の演習問題です.

  7. 本日のまとめ

  8. 宿題

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

  9. 次回の予習範囲

    次回も引き続き教科書のp.113-132(旧版は p.113-129)の範囲を学習しますので,予習をしてきてください.

    次回は多重のループに関する確認テストがありますので,復習もしっかりとしておいてください.


目次ページに戻る