今回は,C言語で作成したプログラムを Python で書き換えてみよう…という試みです
一般的に,Python や R などは,習得しやすいプログラミング言語であると言われています
しかも,すでにC言語でのコーディングができているので,メッチャチョロいと高を括っておりましたら,躓きどころ満載でございました vv
ナメてはいけませんネ,肝に銘じます!!

リスト処理

まだ,Python の入いり口を潜ったばかりですが,Python 攻略のキーはリストかな,と感じました
リストとは,[0, 1, 2, 3] のように,[ ] 括弧の中にカンマで区切った要素をもつという構造のデータです
要素がリストになっている,つまりリストはネストしていても構いません
実は,Pythonの配列変数はリストとして扱われるのです…な~んて知っているような書き方をしていますが,リストって大昔LOGOを使ったときに出てきたなぁ,くらいの知識しかありません f^^;
ただし,リストは数学との相性が良く,リスト処理を得意とする言語の代表がLispでしょう…というくらいのことは数学を教えてきた者として知っています
実際に日々お世話になっている maxima は Lisp で書かれていますし,前述の LOGO もLisp が基になっています
Python が機械学習などに利用される理由も,この辺りにあるのでしょうか

cording

それはさて置き,Python で魔法陣を作るための記述をまず示します
その後,C言語との違いや注意すべき点を述べていきます

まったく,Chromebook の Crostini でプログラミング学習をやっていま~す,などと嘯きながら,チャッカリ paiza.io でのハードコピーを載せていますねぇ
まぁ,これはこれで短いコーディングには具合が宜しいので vv

蛇足ですが,Crostiniは 仮想 linux ですから元々 Python を使うことができます
sudo apt install で anaconda も Jupyter-notebook だけでもインストール可能です
しかし,流石にC223NAでは起動が遅い
加えて,ubuntuではあっさりインストールできた rmaxima が,C223NA にはどうにもインストールすることができません
したがって,Jupyter-notebook 上で maxima を使うことができないのです
ならば,IPythonでいんじゃね…ということで,現在,元々の python3 との併用で IPython を愛用しています

変数

C言語でのコーディング時と同様に定めます

dim 魔法陣の次数を格納します
a[i][j]   第i+1行第j+1列のセルに入る数を格納します
上記のとおり魔法陣のセルの行参照に使います
上記のとおり魔法陣のセルの列参照に使います
num  魔法陣のセルに入れる数を格納し,\(1\) から \(\mbox{dim}^2\) まで変化します

Pythonでは,変数型を明示する必要がありません
「変数=値」という文が記述されたときに,値の形により変数が宣言されます
言い換えると,値なしに変数を宣言することはできません(のようです)
型宣言をしないと気持ち悪いという向きには,「dim: int = 3」のように型(この場合は整数型)を明示する宣言方法もあります
私も,どちらかというと「型宣言をしたい派」だったのですが,この数年Javascriptだけを見てきたせいか,どうでも良くなってしまいました vv

まずは,第1行をご覧ください
dim = input("魔法陣の次数は?:") となっています
dimに値が入って宣言されたということです
さて,どのような変数型になったのでしょうか?

データの入力 input( )

それを知るためには,input( ) の働きを理解しておく必要があります
この関数は,C言語のscanf( )に相当します

input( )

  1. var = input()
    キーボードからの入力を文字列として受け取り,変数varに格納します
  2. var = input(文字列)
    1. との違いは,プロンプト画面に( )内の文字列を表示して,入力を受け付けるところです

データのフォーマットを指定して入力を受け付ける scanf( ) と異なって,Python のinput( ) は常に文字列を受け取ります
したがって,変数 dim はこの時点で文字列型となります
つまり,input( ) でデータを受け取った dim を,そのまま数値として扱うことはできません

そこで登場するのが,第2行にある int( ) 関数です

文字列表記された数の十進数化 int( )

int( )

  1. int(str)
    str(文字列)で表された数を十進数の整数値にします
    《例》int("123") = 123
  2. int(str, base)
    strを第2引数に入った数値baseを基数とする数と見なして,これを十進数の整数値にします
    《例》int("101101", 2) = 45
  3. int(float)
    小数点付きの数値floatに関して,小数点以下を切り捨てて整数値にします
    《例》int(3.14) = 3

しかも,dim = int(dim) でオケマルなのです
これだけで,文字列型であった dim が整数型に変わってしまうのです
このように,変数型を文字列型から整数型に変えることを「文字列型から整数型にキャストする」といい,C言語ではキャスト演算子なるものを用いて明示しなければなりません
ところが,Python では,自動的にキャストが行われるようです(ようですと書いたは,やってみて,どうやら自動だなと考えただけ ^^)

ここだけ見ても,Python ってフレキシブルみが強いですねぇ
新たに出現したプログラミング言語の一般的な特徴であり,それが故に,新しいタイプのプログラミング言語は入門の敷居を低くしています
チョイチョイの余談になりますが,もう一つはライブラリの豊富さも使いやすさを向上させている要因ですね(たぶん,本当はよく知らないけど)

配列の初期化

さて,問題の第4行,配列の初期化です
今回は,与えられた次数によって配列のディメンションを決めて,各要素を \(0\) で初期化します
これが,なかなかに難問でした
考えるのはあきらめ,ググって見つけました

例えば,dim = 5 として,[0] * 5 の演算結果は [0, 0, 0, 0, 0] となります
これを5回繰り返すと
  [[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]]
となって,\(5 \times 5\) の配列の要素を 0 で初期化することができます

繰り返しにはfor構文が使われていますが,これもC言語と異なりますので,for 構文で改めてご説明します

第6行と第7行は,C言語のときと同じです
最下行の真ん中に,i と j を指定しています

繰り返し処理 for構文

for 文

for var in LIST:

(繰り返し処理はインデントして記述)

Pythonは,for 文も極めてフレキシブルです
リストLISTを用意すれば,変数 var に LIST の要素を順に代入して繰り返しの処理をします
LIST の要素は数値である必要はありません
LIST = ["牛", "豚", "鶏"] とすれば,var には "牛", "豚", "鶏" が順に入って,繰り返し処理を3回実行します

C言語のforのように,数値を順次変えて繰り返したい場合には range( ) 関数を使います

range( ) 関数

  1. range(e) = [0, 1, 2, ・・・, e - 1]
    引数が一つの場合には,0 から始まり e - 1 で終わるリスト
  2. range(s, e) = [s, s + 1, ・・・, e - 1]
    引数が二つの場合には,s から始まり e - 1 で終わるリスト
  3. range(s, e, p) = [s, s + p, s + 2p, ・・・]
    引数が三つの場合には,第3引数が刻み値になって,s から始まり p ずつ増え第2引数より小さい値までつづくリスト

したがって,第4行をもう一度見ると,0 から dim - 1 まで繰り返すということが分かると思います
この場合の変数は何でも宜しいのです

for 文の最後には:(コロン) を付けて,繰り返し処理の部分はインデントを下げます
このプログラムでは,第9行の for 文によって,第10行から第15行までが繰り返されます

さて,ここでも注意すべき点があります
繰り返し処理のインデントに,タブと空白が混在してはいけません
通常はエディタが自動でインデント下げを行ってくれます
ところが,それをコピー&ペーストしようとすると,エラーの出る場合があります
見た目にはタブのように見えますし,カーソルを動かしても間違いなくタブです
ところが,英語で「タブと空白が混じっている」と叱られるということがありました
タブらしきものをすべて削除し,改めてタブを打ち直すと正常に動作…謎です
まぁ,開発環境によるものだと思いますが,コピペの場合には注意した方が良さそうです
そう言えば,Windows のメモ帳で作ったファイルを,linux の python3 で動かそうとしたときも叱られました
改めて emacs なり vim なりで確認すると,インデントが滅茶苦茶になっていました
処理の範囲をインデント下げで決めるのは簡単で宜しいと思いますが,そこには予想しなかった落とし穴があるかもしれないと,考えておきましょう

条件分岐処理 if 構文

if 文

  1. if 条件式 :
      条件式が真のときの処理
  2. if 条件式 :
      条件式が真のときの処理
    else:
      条件式が偽のときの処理

文構造はC言語とほぼほぼ同じですが,条件式に括弧をつける必要がなく,処理内容をインデント下げして記述します
条件式が偽のときに,更につづけて条件分岐する場合には「else」の代わりに「elif」を用いて続けます
このプログラムでは,右下のセルの値が 0 であるかを判断して,真ならば次のセルを右下に,偽ならば次のセルを一つ上にそれぞれ移動させています

データの出力 print( )

以上で魔法陣の各セルに入る数値が求められましたから,この数値を縦横が揃うように画面に出力します

print( )

  1. print(データ)
    数値を出力して改行します
  2. print(f文字列データ}
    データを書式付きで出力して改行します
  3. print(データ, end = 文字列)
    データを出力した後,改行コードの代わりに end で示された文字列を出力します
    したがって,改行はされません

出力に書式を設定するためには,format メソッドを使うという方法もあるのですが,オブジェクト指向的なものはまず避けましょう
代わりに,f文字列なるものを用います
f文字列は f'{var: >n}' などの書き方をします
ここでは,数値の桁を揃えて出力したいので,そのような場合の書き方を覚えることにします

  • f'  ' という書き方をして,' ' の中にデータと書式をかきます
    f につづくシングルクォーテーションはダブルクォーテーションでも構いません
  • クォーテーションの中は { } で囲んで,{データ: 書式} という書き方をします
  • 数値の桁指定は数字で行い,<が左詰め,^が中央揃え,>が右詰めを表し,>4 は右詰め4桁で出力することを表します
    なお,書式を指定する際の:の後ろには半角スペースを入れる必要があります

以上で,魔法陣を表すプログラムが完成しました


paiza.io から Jupyter-notebook にコピーして実行してみました
見るとアレアレ?という部分がありますね
インデントが空白で下げられた行と,タブで下げらた行があります
偶々不具合の生じない形になっているので実行できましが,このようなことが生じます

また i と j は,int( ) 関数を使わないと float 型となってしまいます
Python は,数値を基本的に浮動小数点数として扱うのでしょうか?
ん~!! やはり変数の型宣言は大切ですね

最終更新日時: 2022年 03月 11日(金曜日) 17:02