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

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

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

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

3回答

3712閲覧

サイコロ アルゴリズム

退会済みユーザー

退会済みユーザー

総合スコア0

Scala

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2017/10/24 01:49

AIZU ONLINE JUDGEでアルゴリズムの勉強をしているのですが、サイコロの問題で、わからない部分があります。

昨日も、Javaのプログラムで質問させて頂きました。同じ問題なのですが、他の方が書いたScalaのプログラムで、よくわからない部分があります。

Scala

1 2import scala.io.StdIn._ 3 4object Main { 5 6 object Dice{ 7 private val north = List(2,6,3,4,1,5).map(_-1) 8 private val east = List(4,2,1,6,5,3).map(_-1) 9 private val ccw = List(3,2,6,1,5,4).map(_-1) 10 } 11 12 case class Dice(pip: List[Int]) { 13 def north = Dice(Dice.north.map(pip)) 14 def east = Dice(Dice.east.map(pip)) 15 def south = north.north.north 16 def west = east.east.east 17 } 18 19 def main(args: Array[String]): Unit = { 20 val pip = readLine.split(" ").map(_.toInt).toList 21 val commands = readLine 22 23 var dice = Dice(pip) 24 25 for(com <- commands){ 26 dice = com match { 27 case 'N' => dice.north 28 case 'E' => dice.east 29 case 'S' => dice.south 30 case 'W' => dice.west 31 case _ => dice 32 } 33 } 34 35 println(dice.pip(0)) 36 } 37} 38

object Dice{
private val north = List(2,6,3,4,1,5).map(-1)
private val east = List(4,2,1,6,5,3).map(
-1)
private val ccw = List(3,2,6,1,5,4).map(_-1)

Listの中身が、2,6,3,4,1,5になるのは、なぜでしょうか?
northであれば、2,6,5,1だと思うのですが…。

わかる方いらっしゃいましたら、教えて下さい。
よろしくお願い致します。

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

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

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

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

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

guest

回答3

0

この配列は、元のサイコロの面から新たなサイコロの面の対応を示す「置換」を表しています。
例えばnorthの場合、(一旦-1しない配列で説明します)Listが(2,6,3,4,1,5)ですから、
Dice.north.map(pip)の結果は

scala

1List(pip(2), pip(6), pip(3), pip(4), pip(1), pip(5))

つまり、もとのサイコロで2番の位置にあった面が1番の位置に、6番の位置にあった面が2番に来ます。
実際はJavaの配列同様0始まりなので、.map(_-1)によってインデックスを1減らしています。

投稿2017/10/24 02:34

swordone

総合スコア20651

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

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

退会済みユーザー

退会済みユーザー

2017/10/24 03:34

回答ありがとうございます。 転がした後の面を考えているということですね。 そして、配列なので、.map(_-1)しているのですね。 .map(_-1)もよくわかっていなかったので、解説下さり、助かりました。 ありがとうございました。
guest

0

ベストアンサー

「さいころの問題」のページ(質問中のリンク先)のさいころの図(右上にある、各面の番号を示している図)をつかって説明します。

さいころをNorth(N)方向に転がすと、転がす前は1の面が上であったのが、2の面が上になります。
同様に、手前の面は2の面であったのが6の面に、奥の面は5の面であったのが1の面に、底の面は6の面であったのが5の面になり、左右の面は、4の面、3の面のままです。
対応表にすると
転がす前 :1,2,3,4,5,6
転がした後:2,6,3,4,1,5

Northのリストの中身が、2,6,3,4,1,5、になるのは、上記のように北に転がした事による面の変化を表現したものだからです。

質問のコードでは定義されただけで使われていませんが、ccwはcounter-clockwiseの略で、さいころを反時計回りに90度ひねった場合です。

(実際のさいころ(もしくは厚紙で作った立方体)を転がしてみると理解しやすいと思います。頭の中で立体を転がすのは、難しいですから)

投稿2017/10/24 02:25

coco_bauer

総合スコア6915

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

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

退会済みユーザー

退会済みユーザー

2017/10/24 03:31

回答ありがとうございます。 転がした後が、2,6,3,4,1,5となるということですね。 わかりやすい説明ありがとうございます。理解できました。
guest

0

わからない部分があります

プログラマーの意図を汲むには、本件の場合ならprivate val northをどのように使っているかを読み解けば意図は自然に把握できると思います。Diceの回転メソッドの定義をみてみますと

def north = Dice(Dice.north.map(pip))

mapでサイコロの各々の面をどう変化させるべきなのかをマッピングに従って6面全て求めるという方法を使っていますね?

前の質問のJavaプログラマーは「現在の面の状態の中で変化する面のみを破壊的に変更する」方法論を取っていました。

一方このScalaプログラマーは副作用を排除して関数的な方法論で解を求めようとしてます。つまり現在の面の状態を表すインスタンスの内容は変更しないようにし、回転後のダイスの状態を示す新たなインスタンスを生成するという考え方です。新たなインスタンスを生成する際に変更のない面についてもマッピングを用意しておくだけで計算処理が簡潔に書けます。

投稿2017/10/24 02:16

KSwordOfHaste

総合スコア18394

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

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

退会済みユーザー

退会済みユーザー

2017/10/24 03:37

回答ありがとうございます。 Javaとの違いも説明してくださり、ありがとうございます。 Scalaプログラムの考え方の説明も、勉強になりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問