目次: 自宅サーバー
日記にコメントが書けない状態になっていましたが、復旧させました。原因はコメント投稿内容の確認を行う際に、一時的にコメントの下書きを保存するファイルが多数のスパムにより肥大化したこと、のようです。
肝心の下書き保存ファイルが肥大化するとなぜコメントが書き込めなくなるのか?を解析しないうちに直してしまったため、真因まで追えていません。真因が不明なままなので再発の可能性は残りますが、おそらくかなり先のことでしょう。たぶん…。
この記事にコメントする
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 | - |
25年10月15日
25年10月18日
22年5月5日
25年10月19日
23年4月11日
06年4月22日
25年10月17日
25年10月6日
25年10月13日
20年10月23日
25年10月12日
20年8月29日
19年1月13日
18年10月13日
18年9月3日
18年8月20日
18年7月23日
18年7月22日
18年10月14日
18年11月10日
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年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: