ScalaにてBooleanのリストをビット列に見立てて、任意のビット数を上位ビット〜下位ビットにOR演算し、Intのリストとして返すという処理をやりたいのです。
ビット列 (0, 1, 0, 0, 1, 1, 0, 0, 0) に対して、(1ビット取る, 3ビット取る, 5ビット取る) という処理を行って、結果として (0, 4, 24) が返る、そんなイメージです。
いきなり作るとコケたときショックがデカいので、まずは単純化して必ず8ビットずつ取る処理で考えてみます。入力、出力は下記の通りです。
(入力)
List(
true, false, false, true, true, false, true, false,
true, true, true, false, true, false, true, true
)
(出力)
List(154, 235)
やりたいことはシンプルなのですが、あまりスマートな書き方が思いつきません。
まず思いついたのがforeachです。
val a = List(
true, false, false, true, true, false, true, false,
true, true, true, false, true, false, true, true
)
var acc = 0
var p = 0
var b: List[Int] = List()
a.foreach { it =>
acc <<= 1
if (it) acc |= 1
p += 1
if (p >= 8) {
b = b :+ acc
acc = 0
p = 0
}
}
println(b)
動くには動きますが、8ビット読むごとにリストのコピー処理が走るという、富豪プログラミングの限界に挑戦しているようなプログラムです。
次に思い浮かぶのはmap関数ですが、基本的にforeachと変わらないように思います。変換前と変換後が1:1対応するなら簡単に書けますが、n:1対応させると一時変数の隠蔽が必要になり面倒です。
object BooleanToByte {
def apply(): (Boolean => Option[Int]) = {
val o = new BooleanToByte()
o.mapper
}
}
class BooleanToByte() {
private var v = 0
private var p = 0
def mapper(b: Boolean): Option[Int] = {
v <<= 1
if (b) v |= 1
p += 1
if (p >= 8) {
val result = Some(v)
v = 0
p = 0
result
} else {
None
}
}
}
val a = List(
true, false, false, true, true, false, true, false,
true, true, true, false, true, false, true, true
)
val b = a.map(BooleanToByte()).flatten
println(b)
ひとまず見た目をa.map(f) の形に近づけるためだけに頑張りました。コードがダサいというか、Scala初心者感が丸出しというか。もっとスマートに書けるはずですが、今の私のレベルではなんとも…。
ちなみに最後のflattenはSomeオブジェクトを展開して中身の値を取り出すために使っています。ついでにNoneも消してくれるナイスな奴です。
最後にリストの要素を列挙するもう一つの手段、イテレータが思いつきました。foreachと異なりn:1対応に融通が利きます。いや…融通が利くというより、自由に記述できてしまうが故にn:1だろうとn:mだろうと、もはや何でもアリと言った方が正しいですね。
val a = List(
true, false, false, true, true, false, true, false,
true, true, true, false, true, false, true, true
)
val it = a.iterator
var b: List[Int] = List()
while (it.hasNext) {
var acc = 0
var p = 0
while (p < 8) {
acc <<= 1
if (it.next()) acc |= 1
p += 1
}
b = b :+ acc
}
println(b)
先ほどのforeachやmapのような、無理やり頑張った感はなくなったように思いますが、今度は変換元に8未満の要素数が残っているとき、例外がスローされてしまうという欠点もあります。
これがforeachを差し置いてベストか?と言われると、何とも言い難い、難しいですね。
この記事にコメントする
パナソニック“脱家電”路線の衝撃度 松下翁の「水道哲学」は消えるのか
えー。脱家電じゃなくて、脱黒物家電でしょう。
赤字5兄弟が「テレビ、半導体、携帯、回路、光ピック」ならば、携帯以外は全部テレビ関連じゃないですか。脱テレビといっても過言じゃないです。
メモ: 技術系?の話はFacebookから転記しておくことにした。
この記事にコメントする
| < | 2014 | > | ||||
| << | < | 01 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | - | 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 | - |
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: