質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

1112閲覧

Pythonで関数を使わずにループさせたい

kyogym

総合スコア13

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/11/07 14:34

Python(IDLE)でプログラミング教材を作っています。while文やfor文を用いることなく、一言(一単語)の命令でループさせたいです。

発生している問題・エラーメッセージ

初等教育向けのプログラミング教材を開発しています。(専門高校高3)
受験の推薦入試でプレゼンで行うときに使います。
使用するCPUはRaspberry Piで言語はPythonです。
自分が製作した車型のロボットを簡単な命令コードで動作できるようにしたいです。
作りたい命令コードは以下の8つです。

FWD・・・前進 WAT・・・待機
BRK・・・後退 MRK(ⅹ)・・・ⅹは番号
LFT・・・左折 LMP(ⅹ)・・・MRK(x)へジャンプ
RGT・・・右折 SW(ⅹ)・・・MRK(x)へジャンプ

FWD,BRK,LFT,RGT,WATはGPIOによる出力をするプログラムをモジュールにして、
関数として呼び出せるのですが、MRK,JMPに関してはそう簡単にいきませんでした。
MRK,JMPは組み合わせることでループの役割をさせたいです。
そのため、
入力したプログラムを全て読み込む→MRKの行を記憶→JMPを検知→MRKにジャンプ
→JMP以下のプログラムを再実行
の流れで処理する必要がある。と、学校の教諭は言っていました。
以下に記すのが、入力したプログラム例です。

MRK(1) マーク1番を置く
FWD(1.0) 前進(1s)
LFT(1.0) 左折(1s)
JMP(x) マークの1番へジャンプ

以上のプログラムの実行結果としては

 →前進(1s)→左折(s)→
↑          ↓
← ← ← ← ← ← 

です。ループ制御をしたいのです。
しかし、Pythonでプログラムを途中(ここではMRKの後)から実行するやり方が分かりません。

エラーメッセージ

### 該当のソースコード ```Python ソースコード

試したこと

一度書き込んだプログラムを全て読み取りMRK、JMPと名づけた関数の文字列をfind()でみつける

JMPの文字列を取得したらMRKまでジャンプし、MRK以下の命令をまた順番に実行する。事を試みた。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2018/11/07 14:47

①入力は最初に全行与えられるのですか?②ご提示の例の場合、無限ループに陥りますが脱出条件は用意しないのですか?③JMP命令とSW命令の差は何ですか?
kyogym

2018/11/07 14:53

①一行ずつ入力し、保存してから実行します。②用意したいのですが、先ずはループを完成させたいです。③SWはロボットについているリミットスイッチの入力でMARにジャンプさせたいです。分岐命令のようなものにしたいと考えています。
can110

2018/11/07 15:07

まずは途中まででよいのでご自身で書いたコードを提示ください。
guest

回答2

0

どうやら事前に解析する余地があるようですね。
それならば、扱いやすいように命令を書き直してしまっても良いのでは?

例えば、スクリプト読み込み時に次のように処理を置きなおしてやります。

plain

1MRK(1) 2FWD(1.0) 3LFT(1.0) 4JMP(1)

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

plain

1MRK None 2FWD 1.0 3LFT 1.0 4JMP 0 # ジャンプ先の行番号

投稿2018/11/07 15:20

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyogym

2018/11/07 15:24

勉強不足で申し訳ないのですが、この場合MRK,JMPではどのような処理をさせればよいのでしょうか 関数として扱えばよいのでしょうか
LouiS0616

2018/11/07 15:29

リストに全行放り込んで、一行一行処理していけば良いです。 hayataka2049さんが書かれているような、カウンタを用意する方法が最も安直かつ簡単かと思います。 もちろん、OOP的に綺麗に設計・実装できるならそのような開発方針をとっても良いでしょう。
kyogym

2018/11/07 21:23

ご丁寧にありがとうございます アドバイス頂いた通りにやったみたいと思います。
guest

0

ベストアンサー

pythonとしてはgotoはないので、そのままpythonとして実行して望む出力が得られるようなコードを作ることは難しいと思います(もしかしたら誰かが黒魔術で解決する方法を書いてくれるかもだけど)。

簡単とはいえpythonとは別の言語処理系を作ることになるので、相応の気合と知識が要ります。

フロー制御だけできれば良いなら、読み込んだ命令をリストに入れて先頭から逐次実行、JMP系はプログラムカウンタ的な変数を用意しておいてそれを書き換える……みたいな方針で書けるとは思いますが。

追記

一応具体例を書いておきます。

MRK(1) FWD(1.0) LFT(1.0) JMP(x)

を動かすとしたら、

まず読み込んで次のようなフォーマットに変換する。ここは面倒くさいので今回パスします。

python

1instructions = [("MRK", 1), ("FWD", 1.0), ("LFT", 1.0), ("JMP", 1)]

ラベルと命令のindexの対応テーブルを作っておきます。

python

1label_table = dict() 2for i, (ins, arg) in enumerate(instructions): 3 if ins == "MRK": 4 label_table[arg] = i

命令を実際に実行するための関数を書く。なお、各命令の関数は別途用意しておきます。

python

1def exec_instruction(ins, arg): 2 global pc 3 if ins == "FWD": 4 fwd(arg) 5 elif ins == "LFT": 6 lft(arg) 7 # 中略... 8 # JMP系はまた扱いが別 9 elif ins == "JMP": 10 pc = label_table[arg] 11 elif ins == "SW": 12 if スイッチがHなら: 13 pc = label_table[arg] 14 15

あとはメインループを回せば良いです。

pc = 0 while True: if pc >= len(instructions): break exec_instruction(*instructions[pc]) pc += 1

以上をまとめてみました。実行可能です。あまりきれいじゃないんですが、何かの参考にはなると思います。

python

1import time 2 3def fwd(arg): 4 # fwdとlftは自分の名前をprintしてarg秒sleepする関数にしてみました 5 print("fwd") 6 time.sleep(arg) 7 8def lft(arg): 9 print("lft") 10 time.sleep(arg) 11 12def exec_instruction(ins, arg): 13 global pc 14 if ins == "FWD": 15 fwd(arg) 16 elif ins == "LFT": 17 lft(arg) 18 elif ins == "JMP": 19 pc = label_table[arg] 20 else: 21 pass 22 23instructions = [("MRK", 1), ("FWD", 1.0), ("LFT", 1.0), ("JMP", 1)] 24 25label_table = dict() 26for i, (ins, arg) in enumerate(instructions): 27 if ins == "MRK": 28 label_table[arg] = i 29 30pc = 0 31while True: 32 if pc >= len(instructions): 33 break 34 exec_instruction(*instructions[pc]) 35 pc += 1

ぱっと思いつく、他にやらないといけないであろうこと。

  • 構文が間違っていたらわかりやすいエラーを出す
  • MRKで同じラベルを複数作ると困るので、エラーを出すようにする

余談

大学の推薦入試くらいならけっこうウケるかもしれませんが、この「プログラミング言語」にはいろいろ問題があります。

  • 変数がない
  • 状態を持てない
  • よってかなり表現能力は低い
  • あと、初等教育の子たちってパソコンのキーボードを使えるんですか

さらにこの分野ではLEGOのマインドストームという強力な競合があります(他にもあるけど)。私は小学生の頃触っていましたが、けっこう高機能でした。

今から練り直すもよし、あるいはその辺は割り切ってプレゼン力で乗り切るのも一つの戦略です。

投稿2018/11/07 15:12

編集2018/11/07 16:01
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyogym

2018/11/07 15:17

そうですか 残念です ご回答ありがとうございました
hayataka2049

2018/11/07 15:51 編集

一応具体的にはこんな感じかなぁ、というのを追記してみました。ちゃんと使えるようにはしていないので、あくまで参考例として見てください
kyogym

2018/11/08 08:07

事細かに説明してくださってありがとうございます 今回はなんとかプレゼンで乗りきりたいと思います
kyogym

2018/11/08 10:22

今日これと同じようにしてやってみたのですが PC=label_table[arg] で、 NameError:'label_table' is not defined と、エラーが出てしまったのですが何故でしょうか
hayataka2049

2018/11/08 10:28

一番最後のコードをまるごとコピペして実行してもそうなりますか?
kyogym

2018/11/10 09:14

そうしてるつもりです
hayataka2049

2018/11/10 21:28 編集

私の環境では再現していないので、単にコピペのミスか、もしかしたら特殊な環境で実行しているのかもしれません。私は通常のCPython3.5でスクリプトファイルをコマンドラインから実行しています。
kyogym

2018/11/11 06:33

分かりました。自分の中でもう少し咀嚼して、何とかやってみます
kyogym

2018/11/15 06:06

実行出来ました [読み取ってフォーマットに変換]を教えてくださいませんか
hayataka2049

2018/11/15 06:40 編集

テキストのソースファイルを読み込んで同様のフォーマットに変換すれば良いです。受験に使うということなので、あまり他人が助言するのも問題になりますから、ご自身で実装されると良いかと思います。
kyogym

2018/11/19 13:39

そうですね 後は自分で勉強していきたいと思います。 ご指導ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問