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

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

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

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

4回答

2381閲覧

pythonでサイコロの面の場合訳について

babbleman

総合スコア107

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2018/11/15 13:02

こんにちは。
Pythonぜサイコロを回転させるプログラムを作りたいのですが、
「上」なら上方向に一回転
「右」なら右方向に一回転
というようにサイコロを回転させたとします。
この時、一回転ごとに下にくる面が何か、を出力したいです。
私が30分考える限りでは、下面の数字と正面の数字を得て、それらについて全て場合分けする、というやり方しか思いつきませんでした。
このやり方だと6×5×上下右左で120通り自分で場合分けしなければいけません。

それよりもサイコロという形の特性を用いた良い解き方が必ずあるはずです。ただし私には思いつきませんでした。
知恵を拝借したいです。
よろしくお願いします。

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

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

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

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

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

guest

回答4

0

... [上下前後右左]を作って、それぞれ4方向に回転させた時に各値がどう変わるかで4通りの場合分けでいいことに気づきました。...

はい、それで良いと思います。
dict で サイコロを表現し、 4方向の回転のメソッドを定義してみました。

python3

1def up(dice): 2 f, u, d, b = [dice["front"], dice["up"], dice["down"], dice["back"]] 3 dice["front"] = d 4 dice["up"] = f 5 dice["down"] = b 6 dice["back"] = u 7 return dice 8 9def down(dice): 10 f, u, d, b = [dice["front"], dice["up"], dice["down"], dice["back"]] 11 dice["front"] = u 12 dice["up"] = b 13 dice["down"] = f 14 dice["back"] = d 15 return dice 16 17def left(dice): 18 f, l, r, b = [dice["front"], dice["left"], dice["right"], dice["back"]] 19 dice["front"] = r 20 dice["left"] = f 21 dice["right"] = b 22 dice["back"] = l 23 return dice 24 25def right(dice): 26 f, l, r, b = [dice["front"], dice["left"], dice["right"], dice["back"]] 27 dice["front"] = l 28 dice["left"] = b 29 dice["right"] = f 30 dice["back"] = r 31 return dice 32 33def show(dice): 34 print(" ", dice["up"], " ") 35 print(dice["left"], dice["front"], dice["right"], dice["back"]) 36 print(" ", dice["down"], " ") 37 print() 38 39def init_dice(): 40 return { 41 "front": 1, "back": 6, 42 "up": 3, "right": 5, "down": 4, "left": 2 43 } 44 45dice = init_dice() 46show(dice) 47dice = up(dice) 48show(dice) 49dice = down(dice) 50show(dice) 51 52dice = init_dice() 53dice = left(dice) 54show(dice) 55dice = right(dice) 56show(dice)

実行例
イメージ説明

サイコロの展開図を表示するようにしてます。

追記
展開図の様子を 2次元配列(Matrix) で表現し、回転操作を Matrix の乗算で表現することも可能と思います。

追記2
numpy を使って行列の演算で書いて見ました。(乗算だけでできると思っていたが、足し算やその他の演算も使いました)
m.py

python3

1import numpy as np 2 3def up(dice, repeat=1): 4 front_ary = np.array([ 5 [0, 0, 0, 0], 6 [0, 1, 0, 0], 7 [0, 0, 0, 0], 8 [0, 0, 0, 0] 9 ]) 10 11 for i in range(0, repeat % 4): 12 d1 = np.matmul(dice, front_ary)[[1, 2, 3, 0]] 13 d2 = np.matmul(front_ary, dice) 14 d2[1,1] = 0 15 dice = d1 + d2 16 dice[1,3] = dice[3, 1] 17 return dice 18 19def down(dice, count = 1): 20 return up(dice, -count) 21 22def left(dice, repeat=1): 23 return up(dice.transpose(), repeat).transpose() 24 25def right(dice, count = 1): 26 return left(dice, -count) 27 28dice = np.array([ 29 [0, 3, 0, 0], 30 [2, 1, 5, 6], 31 [0, 4, 0, 0], 32 [0, 6, 0, 0] 33]) 34print(dice) 35print(up(dice)) 36print(down(up(dice))) 37print() 38 39print(dice) 40print(left(dice)) 41print(right(left(dice)))

実行例
イメージ説明

投稿2018/11/15 14:35

編集2018/11/16 14:40
katoy

総合スコア22324

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

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

0

サイコロは、hayataka2049さんの指摘の通り、相対する面の合計は7なので4種類になります。(組み合わせは8種類ありますが、回転させると同じになる)したがって、初期設定時にどのサイコロを使うか、上面と正面の値が何か、が決定すると6面の値が決定するので、以後は回転の向きと方向によって値をずらしていけばいいことになります。
つまり、babblemanさんのいう場合分けは4種類×2パターンに整理できると思います。(サイコロが決定していて、上面の値が決まっていると正面が取りうる値は2パターンになる)

理想はサイコロの立体形状をデータに表現して、回転を計算する方法が理想の気がします(これなら「上」や「右」角度で表現できるので、場合分けが不要)がコードが想像できませんでした

投稿2018/11/16 01:26

R.Shigemori

総合スコア3376

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

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

0

サイコロの形は一天地六(1と6が上下として、5234が東西南北に対応)

一天地六(イッテンチロク)とは - コトバンク

基本的には4回要るんじゃないかなぁ。

2連続で同じ方向に回したときは自明ですね。100回連続で同じ方向に回しても自明です。上手く使うと計算ケチれるのかな?


最終的に何が入力で何を出力にすれば良い問題なのか実はよくわからない・・・。

投稿2018/11/15 16:28

編集2018/11/15 16:41
hayataka2049

総合スコア30933

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

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

0

少し考えてみたのですが、初期状態のサイコロ配列
[上下前後右左]を作って、それぞれ4方向に回転させた時に各値がどう変わるかで4通りの場合分けでいいことに気づきました。
ただ、賢いやり方とは言えないと思います。

投稿2018/11/15 13:16

babbleman

総合スコア107

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

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

tiitoi

2018/11/15 13:50 編集

90°回転なら上下左右しかないような気がするのですが、前後とはどういうことでしょうか? --------------------------- 追記 回転方向ではなく、上下前後左右はサイコロの目のことですね。 失礼しました。
tiitoi

2018/11/15 13:53

ちなみに入力として使える情報はなんなのでしょうか? 入力は初期状態の目の状態だけで、その後回転した以降はサイコロの目は一切直接観測できないという認識であっていますか?
babbleman

2018/11/15 14:07

すみません、もう少し具体的に書かせていただきます。 初期状態として与えられているのはサイコロの目の情報、そしてサイコロの向きが与えられます。 そしてそのあとサイコロがどのように回転したかの情報だけが与えられ、仰る通りそのあとのサイコロの状態は観測できないです。 Tiitoiさんが仰る通り、サイコロの状態を表しています。 そしてサイコロの目が回転によってどのように遷移するかで私の場合は4通りで場合分けして、問題は無事に解く事が出来ました。 ただし、全く数学的にスマートさを感じなくてまだ腑に落ちません。
tiitoi

2018/11/15 14:17 編集

サイコロの上の目が上下左右回転した際にそれぞれどう変化するかという4x6の状態遷移図が作れると思いますが、babblemanさんはそのやり方を試されて、それ以外の解き方を質問されているということですよね?
babbleman

2018/11/15 14:21

はい。そうです。 言い方は悪いですが、自分が実装したやり方は、正直小学生でも思いつくと思います。 それよりもサイコロの回転などを考慮した、せめて高校レベルのスマートな解き方が欲しいと考えています。
babbleman

2018/11/15 14:24

それとも、組み合わせは爆発して解析的には無理だと考えて、それならせめて4通りの状態遷移図を書いてコンピュータに任せる、と言うのが一番スマートでしょうか? 最近プログラミングを初めてからアルゴリズムを考えるようになったのですが、数式的に解きたい願望がある自分もいるので、どう天秤にかけたらいいかがよくわからなくなってます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問