Javaでタプル

お仕事でJavaの開発をしているのだけれど、どうしても複数の値を返す必要がいくつかありました。
それ専用のクラスをその都度作るのもイマイチだし、
Object[]で返すのもダサい。
Scalaならタプルが使えるのに・・・。


なので、Javaでタプルを作ってみました。

/** 2つの要素を持つImmutableなタプル */
public class Tuple2<T1, T2> {
    public final T1 _1;
    public final T2 _2;
    public Tuple2(T1 _1, T2 _2) {
        this._1 = _1;
        this._2 = _2;
    }
}


使い方です。

    /** intとStringを返すメソッド. */
    Tuple2<Integer, String> getIntStr() {
        // ...
        return new Tuple2<Integer, String>(5, "ほげ");
    }


    void foo() {
        Tuple2<Integer, String> ret = getIntStr();
        int n = ret._1;
        String s = ret._2;
    }

フィボナッチ数列の拡張

スゴイことを発見してしまった!
フィボナッチ数列を負の方に拡張したら、
符号が交互に変わるフィボナッチ数列だった!

..., -21, 13, -8, 5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8...

隣り合う2項を引き算して求めてます。




まぁ、絶対誰かが先にやってるだろうなぁ〜。

面白そうな問題を見つけたのでScalaで解いてみました。
問題はコチラ
http://nabetani.sakura.ne.jp/hena/ord13updowndouble/

/**
 * 増やす減らす二倍する 〜 横へな 2013.9.6 参考問題
 * @see     http://nabetani.sakura.ne.jp/hena/ord13updowndouble/
 */
import scala.collection.mutable.ListBuffer

object Ord13updowndouble {
    type 手 = Char  // '+'/'-'/'*'
    case class 状態(val 数:Int = 0, val 手順:List[手] = Nil) {
        override def toString = 数 + " 手数=" + 手順.length + " 手順=" + {
            手順.reverse.map{ _ match {
                case '+' => "+1"
                case '-' => "-1"
                case '*' => "*2"
                }
            }.mkString("[", " ", "]")
        }
    }

    /** 引数のそれぞれの状態に対して、次の状態を作成する。 */
    def createNextStatus(stats: List[状態]): List[状態] = {
        val result = new ListBuffer[状態]
        for (s <- stats) {
            if (s.数 != 0) {
                result += new 状態(s.数 - 1, '-' :: s.手順)
            }
            result += new 状態(s.数 + 1, '+' :: s.手順)
            result += new 状態(s.数 * 2, '*' :: s.手順)
        }
        result.toList
    }

    /** 解く。同じ手数で複数の解があれば、すべて返す。 */
    def solv(数:Int):List[状態] = {
        var list = List(new 状態())
        while (true) {
            // 解けた状態を探す。
            val solved = list.filter{s => s.数 == 数}
            if (solved.length != 0) return solved
            list = createNextStatus(list)
        }
        Nil
    }

    def main(args:Array[String]) {
        val solved = solv(59)
        solved foreach println
    }
}

結果

59 手数=9 手順=[+1 +1 *2 *2 *2 -1 *2 *2 -1]
59 手数=9 手順=[+1 *2 *2 *2 *2 -1 *2 *2 -1]

[scala]scala.swing.SplitPaneのバグ

コンストラクタで分割の方向を指定できるのだけれど、VerticalとHorizontalが逆になります。

import scala.swing._

object SplitTest extends SimpleSwingApplication {
  def top = new MainFrame {
    title = "Scala SplitTest"
    contents = new SplitPane(Orientation.Horizontal,
      new Label("Left"),
      new Label("Right"))
  }
}
/*
fsc SplitTest.scala
scala SplitTest
*/

理由は、javax.swing.JSplitPane.HORIZONTAL_SPLIT(値は1) 、またはjavax.swing.JSplitPane.VERTICAL_SPLIT(値は0)を渡してやらなければいけないのだけれど、javax.swing.SwingConstants.HORIZONTAL(値は0)、またはjavax.swing.SwingConstants.VERTICAL(値は1)を渡しています。
ちょうど値が逆になっているのです。

scala/SplitPane.scala at v2.10.3 · scala/scala · GitHub
JSplitPane (Java Platform SE 6)
実は2010年10月ぐらい前から気がついているのだけれど、いまだに直らない。ScalaのSwingって使われてないのかな?

写経

(define (eval exp env)
	(cond ((self-evaluating? exp) exp)
		((variable? exp) (lookup-variable-value exp env))
		((quoted? exp) (text-of-q	uotation exp))
		((assignment? exp) (eval-assignment exp env))
		((definition? exp) (eval-definition exp env))
		((if? exp) (eval-if exp env))
		((lambda? exp)
			(make-procedure (lambda-parameters exp)
				(lambda-body exp)
				env))
		((begin? exp)
			(eval-sequence (begin-actions exp) env))
		((cond? exp) (eval (cond->if exp) env))
		((application? exp)
			(apply (eval (operator exp) env)
			(list-of-values (operands exp) env)))
		(else
			(error "Unknown expression type -- EVAL" exp))))