Language detail: Scala
Coverage: 92.14%
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- 起動オプションの解析 (Nested Flatten)
- echoクライアント (Nested Flatten)
- lessの実装 (Nested Flatten)
- コード圧縮 (Nested Flatten)
- コメントの削除 (Nested Flatten)
codes
変数の初期値
(Nested
Flatten)
scalaの場合変数宣言時に値を設定する必要があるので,未初期化時に値を設定するやり方は用意されていません。Option型は用意されているので,Noneが設定されている場合に限り値を設定する処理を参考までに挙げておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class DefinedOr[T] {
var _v:Option[T] = None
def this(n:T) = { this(); this.v = n }
def v:Option[T] = _v
def v_=(v:T) = { _v = Some(v) }
def ||=(n:T) = { v = v match { case None => n; case Some(x) => x } }
}
object Main {
def main(args:Array[String]) = {
var d:DefinedOr[Int] = new DefinedOr
println(d.v)
d ||= 0
println(d.v)
d ||= 1
println(d.v)
d = new DefinedOr(2)
println(d.v)
d ||= 0
println(d.v)
}
}
|
2^i * 3^j * 5^k なる整数
(Nested
Flatten)
#7638と#7671のやり方で。
see: 「レッツ・チャレンジ! パソコン甲子園」第11回の解答例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import scala.collection.immutable.SortedSet
import scala.collection.immutable.TreeSet
abstract class CHammingNumbers {
def take(n:Int):List[Int]
}
class CHammingNumbersG extends CHammingNumbers {
def next(s:List[Int],h:List[Int]):Tuple2[List[Int],List[Int]] = {
val m:List[Int] = s.zip(List(2,3,5)).map { v => h.apply(v._1)*v._2 }
val n:Int = m.sort { (a,b) => a < b }.head
(s.zip(m).map { v => (v._2 == n) match { case true => v._1 + 1; case _ => v._1 } },h+n)
}
def take(n:Int,s:List[Int],h:List[Int]):Tuple2[List[Int],List[Int]] = n match {
case 0 => (s,h)
case _ => next(s,h) match { case v => take(n-1,v._1,v._2) }
}
def take(n:Int):List[Int] = take(n-1,List(0,0,0),List(1))._2
}
class CHammingNumbersS extends CHammingNumbers {
def next(c:SortedSet[Int]):Tuple2[Int,SortedSet[Int]] = (c.firstKey,(TreeSet(c.firstKey*2,c.firstKey*3,c.firstKey*5)++(c-c.firstKey)))
def take(n:Int,c:SortedSet[Int]):List[Int] = n match {
case 0 => List()
case _ => next(c) match { case v => v._1::take(n-1,v._2) }
}
def take(n:Int):List[Int] = take(n,TreeSet(1))
}
object HammingNumbers {
def main(args:Array[String]):Unit = {
try {
val n:Int = args.length match {
case 1 => args(0).toInt
case _ => 100
}
List(new CHammingNumbersG,new CHammingNumbersS).foreach { h => println(h.take(n).mkString("\n")) }
} catch {
case e => e.printStackTrace
}
}
}
|
Streamを使って書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | object HammingNumbers {
def from(n:Int):Stream[Int] = Stream.cons(n,from(n+1))
def hammings(s:Stream[Int]):Stream[Int] = {
def divide(n:Int,b:Int):Int = (n % b == 0) match {
case false => n
case _ => divide(n/b,b)
}
Stream.cons(s.head,hammings(s.tail.filter { n => List(2,3,5).foldLeft(n) { (v,b) => divide(v,b) } == 1 }))
}
def hammings():Stream[Int] = hammings(from(1))
def main(args:Array[String]):Unit = {
try {
val n:Int = args.length match {
case 1 => args(0).toInt
case _ => 100
}
println(hammings().take(n).mkString("\n"))
} catch {
case e => e.printStackTrace
}
}
}
|
[1..100]>>=penさんの投稿を参考に書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class CHummingNumbers {
def next(c:Int):Int = (BigInt(30).pow(c) % c).intValue match {
case 0 => c
case _ => next(c+1)
}
def take(n:Int,c:Int):List[Int] = n match {
case 0 => List()
case _ => next(c) match { case v => v::take(n-1,v+1) }
}
def take(n:Int):List[Int] = take(n,1)
}
object HummingNumbers {
def main(args:Array[String]):Unit = {
try {
val n:Int = args.length match {
case 1 => args(0).toInt
case _ => 100
}
println((new CHummingNumbers).take(n).mkString("\n"))
} catch {
case e => e.printStackTrace
}
}
}
|
LL Golf Hole 9 - トラックバックを打つ
(Nested
Flatten)
scalaで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import java.io._
import java.net._
val c = (new URL("http://ll.jus.or.jp/2008/blog/archives/38/trackback")).openConnection.asInstanceOf[HttpURLConnection]
c.setRequestMethod("POST")
c.setDoOutput(true)
val o = new OutputStreamWriter(c.getOutputStream)
o.write("title=LL+Golf+Hole+9&excerpt=trackback+from+LL+Golf+Hole+9.&url=http://ja.doukaku.org/207/&blog_name=LL+Golf+Hole+9")
o.flush
o.close
val i = new BufferedReader(new InputStreamReader(c.getInputStream))
while (i.ready) {
println(i.readLine)
}
c.disconnect
|
与えられた並べ替えを実現するあみだくじの生成
(Nested
Flatten)
ソートを掛ける方法で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | class CGhostLeg(g:List[Int]) {
val s:List[Int] = g.sort { (a,b) => a < b }
var p:List[List[Boolean]] = List()
def create:CGhostLeg = {
def _calc(c:List[Int],r:Tuple2[List[Int],List[Boolean]]):Tuple2[List[Int],List[Boolean]] = c match {
case List() => r
case h::List() => (r._1+h,r._2)
case h::t => h.compare(t.head) match {
case p if p > 0 => _calc(c.slice(2).asInstanceOf[List[Int]],(r._1+c.apply(1)+h,r._2+true++(t match { case h::List() => List(); case _ => List(false) })))
case _ => _calc(t,(r._1+h,r._2+false))
}
case _ => r
}
def _step(c:List[Int]):Unit = {
val n = _calc(c,(List(),List()))
p = n._2::p
if (!n._1.zip(s).filter { d => d._1 != d._2 }.isEmpty) _step(n._1)
}
_step(g)
this
}
def print:Unit = {
def _join(d:String,l:List[String]):String = l.head + l.tail.foldLeft("") { (s,e) => s + d + e }
println(_join(" ",s.map { e => e.toString }))
p.foreach { l =>
println(_join("|",""::(l.map { e => e match { case true => "-"; case _ => " " } })+""))
}
println(_join(" ",g.map { e => e.toString }))
}
}
object GhostLeg {
def main(args:Array[String]):Unit = {
try {
var g:List[Int] = args.length match {
case 0 => List(3,5,2,4,0,1)
case _ => args.toList.map { s => s.toInt }
}
(new CGhostLeg(g)).create.print
} catch {
case e => e.printStackTrace
}
}
}
|
魔方分割数
(Nested
Flatten)
Pentium1.6GHzの端末で17分少し掛かりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import java.text.SimpleDateFormat
import java.util.Calendar
class CMagicNumber(n:Int) {
val m:Int = n * n
val a:Int = n * (n * n + 1) / 2
def calc:Int = {
def _calc(p:Int,c:Int,s:Int,r:List[Int],g:Int):Int = r match {
case List() => g + 1
case _ => c match {
case 0 => _calc(r.head,1,r.head,r.tail, g)
case _ => r.filter { d => d > p }.foldLeft(g) { (g,d) =>
((c == n - 1) && (s + d == a)) match {
case true => _calc(0,0,0,r.filter { e => e != d },g)
case _ => (d + s >= a) match {
case true => g
case _ => _calc(d,c + 1,s + d,r.filter { e => e != d },g)
}
}
}
}
}
_calc(0,0,0,(1 to m).toList,0)
}
}
object MagicNumber {
def printTime:Unit = println((new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")).format(Calendar.getInstance.getTime))
def main(args:Array[String]):Unit = {
try {
printTime
printf("result:%d\n",(new CMagicNumber(args.length match { case 1 => args(0).toInt; case _ => 5 })).calc)
printTime
} catch {
case e => e.printStackTrace
}
}
}
|
文字列型日時ののN秒後時間取得
(Nested
Flatten)
Javaと余り変わりませんがscala版を。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
object DateEx {
val formatter:DateFormat = new SimpleDateFormat("yyyyMMddHHmmss")
def DateEx(date:String,diff:Int):String = {
val calendar:Calendar = Calendar.getInstance
calendar.setTime(formatter.parse(date))
DateEx(calendar,diff)
}
def DateEx(diff:Int):String = DateEx(Calendar.getInstance,diff)
def DateEx(calendar:Calendar,diff:Int):String = {
calendar.add(Calendar.SECOND,diff)
formatter.format(calendar.getTime)
}
def main(args:Array[String]):Unit = {
try {
args.length match {
case 2 => println(DateEx(args(0),args(1).toInt))
case 1 => println(DateEx(args(0).toInt))
case _ => println(DateEx("20080827235925",40))
}
} catch {
case ex:ParseException => println("invalid date format.")
case ex => ex.printStackTrace
}
}
}
|
tailの実装
(Nested
Flatten)
オプションの処理にかなり場所をとられてしまっていますが...。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import java.io.FileNotFoundException
import java.io.File
import java.io.FileInputStream
import scala.collection.mutable.HashMap
class InvalidArgumentException extends Exception {}
class GetOpt(f:String) {
var _params:List[Tuple2[String,Boolean]] = null
var _opt:HashMap[Any,Any] = null
var _rest:Array[String] = null
_params = f.toList.foldLeft(List[Tuple2[String,Boolean]]()) { (l,c) =>
c match {
case ':' => l match {
case List() => throw new InvalidArgumentException
case h::r => (h._1,true)::r
}
case k => (k.toString,false)::l
}
}.reverse
def parse(a:Array[String]):GetOpt = {
def _parse(o:HashMap[Any,Any],l:List[String]):Tuple2[HashMap[Any,Any],List[String]] = l match {
case List() => (o,List())
case h::r => h.toList match {
case '-'::k => {
_params.find { e => e._1 == new String(k.toArray) } match {
case Some(Tuple2(_,true)) => {
if (r.size == 0) throw new InvalidArgumentException
o.update(new String(k.toArray),r.head)
_parse(o,r.tail)
}
case Some(Tuple2(_,false)) => {
o.update(new String(k.toArray),true)
_parse(o,r)
}
case _ => throw new InvalidArgumentException
}
}
case _ => (o,l)
}
}
_parse(new HashMap[Any,Any],a.toList) match {
case Tuple2(o,r) => { _opt = o; _rest = r.toArray }
}
this
}
def getopt(k:String):Any = _opt.isDefinedAt(k) match {
case true => _opt.apply(k)
case _ => false
}
def rest:Array[String] = _rest
}
class CTail(n:Int,f:Boolean,i:File) {
val s:FileInputStream = new FileInputStream(i)
def this(o:GetOpt) =this(o.getopt("n") match { case Some(false) => 10; case n => n.asInstanceOf[String].toInt },o.getopt("f").asInstanceOf[Boolean],new File(o.rest.apply(0)))
def tailn:Unit = {
val BUF_SIZE:Int = 4096
val e:Long = i.length
def _tailn(p:Long,n:Int,b:Array[Byte]):Array[Byte] = {
var t:Array[Byte] = null
var l:Int = n
(p > BUF_SIZE) match {
case true => {
t = new Array[Byte](BUF_SIZE)
s.getChannel.position(p - BUF_SIZE)
s.read(t,0,BUF_SIZE)
}
case _ => {
t = new Array[Byte](p.toInt)
s.read(t,0,p.toInt)
}
}
t = t.reverse.takeWhile { c => if (c == '\n') l = l - 1; (l > 0) }.reverse
((p <= BUF_SIZE) || (l == 0)) match {
case true => t ++ b
case _ => _tailn(p - BUF_SIZE, l, t ++ b)
}
}
print(new String(_tailn(e, n, new Array[Byte](0))))
s.getChannel.position(e)
}
def tailf:Unit = {
def _tailf(b:List[Byte]):List[Byte] = {
val c:Int = s.read
(c >= 0) match {
case true => _tailf(b + c.toByte)
case _ => b
}
}
print(new String(_tailf(List[Byte]()).toArray))
Thread.sleep(100)
tailf
}
def tail:CTail = {
tailn
if (f) tailf
this
}
def close:Unit = s.close
}
object Tail {
def main(args:Array[String]):Unit = {
try {
val o:GetOpt = new GetOpt("n:f").parse(args)
(new CTail(o)).tail.close
} catch {
case e:InvalidArgumentException => println("usage: scala Tail [-n <number of lines>] [-f] file")
case e:FileNotFoundException => print("file not found.")
case e:Exception => e.printStackTrace
}
}
}
|
LL Golf Hole 7 - バイト数を読みやすくする
(Nested
Flatten)
scalaで書く甲斐の無い感じのソースですが...。
1 | val v=args(0);val w=(v.size-1)/3;printf("%.1f%c",v.toDouble/Math.pow(1000,w)," kMGTPEZY"(w))
|
LL Golf Hole 8 - 横向きのピラミッドを作る
(Nested
Flatten)
インタプリタ起動もできるのですねぇ...。知りませんでした。
1 | val n=readInt;for(i<-(-n+1 to n-1))println("*"*(n-i.abs))
|
LL Golf Hole 6 - 10進数を2進数に基数変換する
(Nested
Flatten)
効率無視、副作用なし、ユーティリティメソッドを使わないを目標に作っています。
scala h6.scala 1234 などで動作させます。
scala h6.scala 1234 などで動作させます。
1 2 | def b(i:Int,s:String):String=if(i>0) b(i/2,""+(i%2)+s) else s
println(b(args(0).toInt,""))
|
LL Golf Hole 1 - tinyurl.comを使ってURLを短縮する
(Nested
Flatten)
かなり無駄なバージョン。
GETですけどAPIを使わずにTinyURLを取得して、Regexで抜き出してます。
scala h13.scala で動かします。
GETですけどAPIを使わずにTinyURLを取得して、Regexで抜き出してます。
scala h13.scala で動かします。
1 2 3 4 5 | import io._
val url="http://ll.jus.or.jp/2008/info/xgihyo"
val t=new StringBuilder;for(c<-Source.fromURL("http://tinyurl.com/create.php?url="+url))t.append(c);
val r="""(?is).*characters:\s+<blockquote><b>([^\s]*)</b><br>.*</blockquote>.*""".r
t.toString match{case r(tu)=>println(tu) case _ =>}
|
LL Golf Hole 7 - バイト数を読みやすくする
(Nested
Flatten)
サンプルと同じく1000で単位を揃えています。
いつものごとくひねりはありません。再帰呼出でループを表現しています。
あまり大きな数になると表示がおかしくなります:-)。
scala h7.scala 1234.5 で動作させます。
いつものごとくひねりはありません。再帰呼出でループを表現しています。
あまり大きな数になると表示がおかしくなります:-)。
scala h7.scala 1234.5 で動作させます。
1 2 3 4 | val b=args(0).toDouble
val u=" kMGTPEZY"
def p(d:Double,c:Int){if(d<1000D||c==(u.length-1))printf("%.1f%c",d,u(c))else p(d/1000D,c+1)}
p(b,0)
|
LL Golf Hole 5 - 最上位の桁を数え上げる
(Nested
Flatten)
効率は無視、再帰呼出でループを表現してみました。
例のごとくひねりはありません。
表示すべき数字は文字列で生成してたりして、かなり卑怯な気がします(^^;。
scala h5.scala で実行します。
例のごとくひねりはありません。
表示すべき数字は文字列で生成してたりして、かなり卑怯な気がします(^^;。
scala h5.scala で実行します。
1 2 3 4 5 | val n=args(0).toInt
def p(i:Int,c:Int){
val v=(""+i+("0"*c)).toInt;if(v<=n){println(v);if(i<9)p(i+1,c)else p(1,c+1)}
}
p(0,0)
|
LL Golf Hole 1 - tinyurl.comを使ってURLを短縮する
(Nested
Flatten)
scala.io.Sourceを使ってストリームを出力してみる。
Scalaはscalaパッケージから相対的に名前空間にアクセスできるのでscala.io.Sourceではなくてio.Sourceでも問題ない。
なおSourceはソースファイルを読み込むためのクラスであるため本来の使い方じゃないし、文字エンコードもutf-8をデフォルトにしているので、アレではある。
scala h1.scala で実行。
Scalaはscalaパッケージから相対的に名前空間にアクセスできるのでscala.io.Sourceではなくてio.Sourceでも問題ない。
なおSourceはソースファイルを読み込むためのクラスであるため本来の使い方じゃないし、文字エンコードもutf-8をデフォルトにしているので、アレではある。
scala h1.scala で実行。
1 | for(c<-io.Source.fromURL("http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo")) print(c)
|
LL Golf Hole 2 - 文字列に含まれる単語の最初の文字を大文字にする
(Nested
Flatten)
短い解答はもうあるのでRegexにこだわって。capitalizeあるのか。というわけでcapitalizeバージョン。
1 | for(a<-"\\w+\\s*".r.findAllIn(args(0)))print(a.capitalize)
|
LL Golf Hole 4 - 文章から単語の索引を作る
(Nested
Flatten)
かなり正攻法に作ってみました。ひねりなしです。
ファイルの読み込みにscala.io.Sourceを使いUTF-8で行ごと読んでいます。語句は単純にRegexで検索して取得して、それらを辞書に追加しています。
行番号取得が面倒だったのでIterator#zipWithIndexを使いました。
scala h4.scala で実行です。
ファイルの読み込みにscala.io.Sourceを使いUTF-8で行ごと読んでいます。語句は単純にRegexで検索して取得して、それらを辞書に追加しています。
行番号取得が面倒だったのでIterator#zipWithIndexを使いました。
scala h4.scala で実行です。
1 2 3 4 5 6 | import collection._
import collection.mutable._
val d=new HashMap[String,Buffer[Int]]
for((l,i)<-io.Source.fromURL("http://www.gnu.org/licenses/gpl.txt").getLines.zipWithIndex)
for(w<-"\\w+".r.findAllIn(l))d.put(w,(if(d.contains(w))d(w)else new ArrayBuffer[Int])+(i+1))
println(d)
|
LL Golf Hole 3 - 13日の金曜日を数え上げる
(Nested
Flatten)
next >>
今回は結構まじめに実装してみました。
副作用のある操作は結構あるような気はしますが(Calendar周り)、なるべく副作用をさけ、かつ、再起呼び出しでカウントしてみました。
副作用のある操作は結構あるような気はしますが(Calendar周り)、なるべく副作用をさけ、かつ、再起呼び出しでカウントしてみました。
1 2 3 4 5 6 7 8 9 | import java.util._
import java.util.Calendar._
def ci=Calendar.getInstance
val f=new java.text.SimpleDateFormat("yyyy-MM-dd")
val c=ci
val e={val v=ci;v.setTime(f.parse("2013-12-31"));v}
def fri={c.set(DAY_OF_MONTH, 13);c.get(DAY_OF_WEEK)==FRIDAY}
def fs(s:Int):Int=if(c.after(e)) s else{c.add(MONTH, 1);if(fri){println(f.format(c.getTime));fs(s+1)}else fs(s)}
println(fs(if(c.get(DAY_OF_MONTH)>=13&&fri) 1 else 0))
|

takeo #7743() [ Scala ] Rating0/0=0.00
あまりScalaらしくありませんが...。
object Tsv { def tsv(text:String) : Unit = { import scala.io.Source val lines = Source.fromString(text).getLines print(lines.next) val data = lines.map({s:String => s.split("\t")}) val lst = List.fromIterator(data).sort({(a:Array[String], b:Array[String]) => Integer.parseInt(a(0)) < Integer.parseInt(b(0))}) for (line <- lst) {print(line(0) + "\t" + line(1) + "\t" + line(2) + "\t" + line(3))} } def main(args : Array[String]) : Unit = { val testData = "ID\tSurname\tForename\tAge\n1\tSato\tHanako\t17\n0\tSuzuki\tTaro\t18\n" tsv(testData) } }Rating0/0=0.00-0+
[ reply ]