link もっと前
   2014年 1月 7日 -
      2013年 12月 29日  
link もっと後

link 未来から過去へ表示(*)
link 過去から未来へ表示

日々

link permalink

コメント

日記にコメントが書けない状態になっていましたが、復旧させました。

原因はコメント投稿内容の確認を行う際に、一時的にコメントの下書きを保存するファイルが多数のスパムにより肥大化したこと、のようです。

肝心の下書き保存ファイルが肥大化するとなぜコメントが書き込めなくなるのか?を解析しないうちに直してしまったため、真因まで追えていません。

真因が不明なままなので再発の可能性は残りますが、おそらくかなり先のことでしょう。たぶん…。

[編集者: すずき]
[更新: 2014年 1月 7日 23:37]
link 編集する

コメント一覧

  • すずき 
    コメントのテスト、その 2。 
    (2014年01月07日 23:34:10)
  • すずき 
    てすと 
    (2014年03月14日 23:06:27)
  • すずき 
    また書き込めなくなった…。 
    (2014年03月14日 23:12:36)
  • すずき 
    これでどうだろう。 
    (2014年03月14日 23:30:03)
open/close この記事にコメントする



link permalink

Scala でバイナリ解析

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 で書く

まず思いついたのが foreach です。

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 関数で書く

次に思い浮かぶのはmap 関数ですが、基本的に foreach と変わらないように思います。変換前と変換後が 1:1 対応するなら簡単に書けますが、n:1 対応させると一時変数の隠蔽が必要になり面倒です。

map の場合

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 も消してくれるナイスな奴です。

iterator はどうか?

最後にリストの要素を列挙するもう一つの手段、イテレータが思いつきました。foreach と異なり n:1 対応に融通が利きます。いや…融通が利くというより、自由に記述できてしまうが故に n:1 だろうと n:m だろうと、もはや何でもアリと言った方が正しいですね。

iterator の場合

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 を差し置いてベストか?と言われると、何とも言い難い、難しいですね。

[編集者: すずき]
[更新: 2014年 1月 7日 08:56]
link 編集する

コメント一覧

  • よしだ 
    ふむふむ。。
    私はRubyで考えてみます! 
    (2014年01月08日 01:48:04)
  • すずき 
    (いけじからの Facebook コメント転記)
    val b = List(false, true, false, false, true, true, false, false, false)
    val c = List(1,3,5)
    に対して、case ((i,o),n)=>(i.drop(n),i.take(n)::o)._2.reverse.map{bs=>bs.map{b=>if(b) 1 else 0}.fold(0){(i,b)=>i*2+b}}.toList\nとかやりたいんですが、色々汚ないですね。 
    (2014年01月11日 14:05:26)
  • すずき 
    (Facebook コメント転記)
    やりたいことはなんとなくわかりますが、かなりゴチャゴチャしますね。
    やはりイテレータでがんばるか。 
    (2014年01月11日 14:06:07)
  • すずき 
    (いけじからの Facebook コメント転記)
    整理してこんな感じです。
    https://gist.github.com/anonymous/9d3cf430f76293b8b36c 
    (2014年01月11日 14:06:43)
  • すずき 
    (Facebook コメント転記)
    print入れまくってやっと意味がわかりました。
    foldLeftってタプル返せるんですね。応用が利きそうです。 
    (2014年01月11日 14:07:28)
  • すずき 
    >よしださん
    どの言語でも、速くて読みやすい、を目指すと難しそうですね。 
    (2014年01月11日 14:31:42)
  • IKeJI 
    Rubyで、int,short,longしか出てこないなら、
    pack、unpackだけでできないかな。 
    (2014年01月11日 17:11:25)
open/close この記事にコメントする



link permalink

脱家電?

パナソニック“脱家電”路線の衝撃度 松下翁の「水道哲学」は消えるのか

えー。脱家電じゃなくて、脱黒物家電でしょう。

赤字 5兄弟が「テレビ、半導体、携帯、回路、光ピック」ならば、携帯以外は全部テレビ関連じゃないですか。脱テレビといっても過言じゃないです。

メモ: 技術系?の話は Facebook から転記しておくことにした。

[編集者: すずき]
[更新: 2014年 3月 17日 00:24]
link 編集する

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
   2014年 1月 7日 -
      2013年 12月 29日  
link もっと後

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 10/13 23:20

カレンダー

<2014>
<<<01>>>
---1234
567891011
12131415161718
19202122232425
262728293031-

最近のコメント 5件

  • link 19年09月01日
    すずき 「私も正直びっくりです。間違って違う製品を...」
    (更新:09/04 23:39)
  • link 19年09月01日
    hdk 「車向けの製品の中でも、車載コンピューター...」
    (更新:09/02 23:20)
  • link 19年07月18日
    hdk 「あっ、AAMはマニュアルのオペレーション...」
    (更新:07/25 00:02)
  • link 19年07月18日
    すずき 「AAM(ASCII Adjust AX ...」
    (更新:07/24 22:22)
  • link 19年07月18日
    hdk 「加算減算は符号のありなしどちらも命令が同...」
    (更新:07/24 07:25)

最近の記事 3件

link もっとみる
  • link 19年10月06日
    すずき 「[RISC-V のバイナリダンプを逆アセンブルする] 相変わらず空...」
    (更新:10/13 23:20)
  • link 19年10月12日
    すずき 「[台風 19号] あの台風 15号(Faxai)(2019年 9月...」
    (更新:10/13 22:04)
  • link 19年09月08日
    すずき 「[台風 15号] 超強力な台風 15号(Faxai)が来るというこ...」
    (更新:10/13 22:03)

こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報