scala練習問題(14)-モードマッチングとサンプルクラス
12014 ワード
14.1 JDK発行パッケージにはsrcがあります.zipファイルにはJDKのほとんどのソースコードが含まれています.サンプルラベルを解凍して検索します(正規表現case[^:]+:).検索して//で始まり[Ff]allsを含みますか?thrのコメントは、//Falls throughや//just fall thruのようなコメントをキャプチャします.JDKのプログラマーたちがJava符号化の習慣を守っていると仮定して、注釈を書く場所にこれらの注釈を書いたとしますが、どのくらいの割合のサンプルが次の分岐に落ちるのでしょうか.理解できなかった=.14.2パターンマッチングを利用して、1つのswap関数を編纂して、1つの整数の対偶を受け入れて、対偶の2つの構成部品の交換位置の新しい対偶偏関数の使い方を返して、使用する時パラメータのタイプを制定することができる
14.3パターンマッチングを利用して、swap関数を作成し、配列中の最初の2つの要素の位置を交換し、前提条件は配列長が少なくとも2つの配列マッチングであり、残りのすべてのパラメータの表現方式は_*である.変数名の代わりにar@*
14.4 ItemのサブクラスとしてサンプルクラスMultipleを追加します.例えば、Multiple(10,Article(「Blackwell Toster」)は、10個のトースターを記述する.もちろん、Bundleでも別のMultipleでも、2番目のパラメータの位置で任意のItemを受け入れることができます.price関数を拡張して、新しいサンプルに対応します.
14.5リーフノードにのみ値を格納するツリーをリストで作成できます.たとえば、リスト((3 8)2(5))は、*/|*2*/|3 8 5というツリーを記述しますが、リスト要素の中には数字であり、リストであるものもあります.Scalaでは異機種リストを持つことができないので、List[Any]を使用する必要があります.leafSum関数を作成し、すべてのリーフノードの要素の和を計算し、パターンマッチングで数字とリストを区別します.
14.6このような木を作るより良い方法はサンプル類を使うことです.二叉木から始めてもいいです.
sealed abstract class BinaryTree case class Leaf(value : Int) extends BinaryTree case class Node(left : BinaryTree,right : BinaryTree) extends BinaryTree
すべてのリーフノードの要素の和を計算する関数を作成します.
サンプルクラスを使用するには、このクラスがこのファイル内にのみ表示されることを示すシールクラスの形式を使用することを推奨します.
14.7前の練習中のツリーを拡張して、各ノードが任意に多くの子孫を持つことができ、leafSum関数を再実現する.5番目の問題のツリーは、次のコードで表すことができます.
14.8前の練習中のツリーを拡張し、各非リーフノードが子孫を除いてオペレータを保存できるようにします.次にeval関数を作成して値を計算します.たとえば、+/|*2-/|3 8の木の値は(3*8)+2+(-5)=21です.
14.9リスト[Option[Int]]のすべてのNone値の和を計算する関数を記述する.match文は使用できません.
14.10 Double=>Option[Double]という2つのタイプの関数を組み合わせて、同じタイプの別の関数を生成する関数を作成します.いずれかの関数がNoneを返す場合は、組合せ関数もNoneを返します.例:
def swap[W,Y](tup:(W,Y))={
tup match{
case (a,b) => (b,a);
}
}
14.3パターンマッチングを利用して、swap関数を作成し、配列中の最初の2つの要素の位置を交換し、前提条件は配列長が少なくとも2つの配列マッチングであり、残りのすべてのパラメータの表現方式は_*である.変数名の代わりにar@*
def swap(arr:Array[Int])={
arr match{
case Array(a,b,ar@_*) => Array(b,a,ar);
}
}
14.4 ItemのサブクラスとしてサンプルクラスMultipleを追加します.例えば、Multiple(10,Article(「Blackwell Toster」)は、10個のトースターを記述する.もちろん、Bundleでも別のMultipleでも、2番目のパラメータの位置で任意のItemを受け入れることができます.price関数を拡張して、新しいサンプルに対応します.
abstract class item;
case class Article(description:String,price:Double) extends item;
case class Bundle(description:String,discount:Double,items:item*) extends item;
case class Multiple(count:Int,item :item) extends item;
def price(it:item):Double = it match{
case Article(_,p)=>p;
case Bundle(_,disc,its @ _ *)=>its.map(price).sum -disc;
case Multiple(count,it) => price(it)*count;
}
14.5リーフノードにのみ値を格納するツリーをリストで作成できます.たとえば、リスト((3 8)2(5))は、*/|*2*/|3 8 5というツリーを記述しますが、リスト要素の中には数字であり、リストであるものもあります.Scalaでは異機種リストを持つことができないので、List[Any]を使用する必要があります.leafSum関数を作成し、すべてのリーフノードの要素の和を計算し、パターンマッチングで数字とリストを区別します.
def LeafSum(li:List[Any]):Int={
var sum=0;
li.foreach{
l => l match{
case list:List[Any] => sum=sum+LeafSum(list);
case t:Int=>sum=sum+t;
}
}
sum;
}
println(LeafSum(List(List(3,8),2,List(5))));
14.6このような木を作るより良い方法はサンプル類を使うことです.二叉木から始めてもいいです.
sealed abstract class BinaryTree case class Leaf(value : Int) extends BinaryTree case class Node(left : BinaryTree,right : BinaryTree) extends BinaryTree
すべてのリーフノードの要素の和を計算する関数を作成します.
サンプルクラスを使用するには、このクラスがこのファイル内にのみ表示されることを示すシールクラスの形式を使用することを推奨します.
sealed abstract class BinaryTree;
case class Leaf(value:Int) extends BinaryTree;
case class Node(left:BinaryTree,right:BinaryTree) extends BinaryTree;
case class Nodes(btree:BinaryTree*) extends BinaryTree;
case class sNode(oper:String,node:BinaryTree*) extends BinaryTree;
def leafsum(btree:BinaryTree):Int={
var sum=0;
btree match{
case Node(a,b) =>sum=sum+leafsum(a)+leafsum(b);
case Leaf(a) => sum=sum+a;
case Nodes(btr@_*) => sum=sum+btr.map(leafsum).sum;
}
sum
}
14.7前の練習中のツリーを拡張して、各ノードが任意に多くの子孫を持つことができ、leafSum関数を再実現する.5番目の問題のツリーは、次のコードで表すことができます.
sealed abstract class BinaryTree;
case class Leaf(value:Int) extends BinaryTree;
case class Node(left:BinaryTree,right:BinaryTree) extends BinaryTree;
case class Nodes(btree:BinaryTree*) extends BinaryTree;
case class sNode(oper:String,node:BinaryTree*) extends BinaryTree;
def leafsum(btree:BinaryTree):Int={
var sum=0;
btree match{
case Node(a,b) =>sum=sum+leafsum(a)+leafsum(b);
case Leaf(a) => sum=sum+a;
case Nodes(btr@_*) => sum=sum+btr.map(leafsum).sum;
}
sum
}
14.8前の練習中のツリーを拡張し、各非リーフノードが子孫を除いてオペレータを保存できるようにします.次にeval関数を作成して値を計算します.たとえば、+/|*2-/|3 8の木の値は(3*8)+2+(-5)=21です.
sealed abstract class BinaryTree;
case class Leaf(value:Int) extends BinaryTree;
case class Node(left:BinaryTree,right:BinaryTree) extends BinaryTree;
case class Nodes(btree:BinaryTree*) extends BinaryTree;
case class sNode(oper:String,node:BinaryTree*) extends BinaryTree;
def leafsum(btree:BinaryTree):Int={
var sum=0;
btree match{
case Node(a,b) =>sum=sum+leafsum(a)+leafsum(b);
case Leaf(a) => sum=sum+a;
case Nodes(btr@_*) => sum=sum+btr.map(leafsum).sum;
}
sum
}
def eval(btree:BinaryTree):Int={
btree match{
case sNode(oper,btr@_*) => if(oper=="+") btr.map(eval).sum else if(oper=="*") btr.map(eval).reduceLeft(_*_) else if(oper=="-") btr.map(eval).foldLeft(0)(_-_) else btr.map(eval).reduceLeft(_/_)
case Leaf(v)=>v
}
}
14.9リスト[Option[Int]]のすべてのNone値の和を計算する関数を記述する.match文は使用できません.
def evalList(list:List[Option[Int]]):Int={
list.map(_.getOrElse(0)).sum;
}
14.10 Double=>Option[Double]という2つのタイプの関数を組み合わせて、同じタイプの別の関数を生成する関数を作成します.いずれかの関数がNoneを返す場合は、組合せ関数もNoneを返します.例:
def f(x:Double) = if(x>=0) Some(sqrt(x)) else None;
def g(x:Double) = if(x!=1) Some(1/(x-1)) else None;
def compose(x:Double=>Option[Double],y:Double=>Option[Double]):(Double=>Option[Double])={
(f:Double) => if(x(f)==None || y(f)==None) None else if(x(f).get> y(f).get) x(f) else y(f)
}