From 8b3cc4835c4c77df9f207bd342ffd024f0f726e7 Mon Sep 17 00:00:00 2001 From: iximeow Date: Wed, 26 Nov 2014 00:41:34 -0800 Subject: Rest of challenge 6 also hacking junk around the frequency maps. --- src/utils/ByteUtils.scala | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'src/utils/ByteUtils.scala') diff --git a/src/utils/ByteUtils.scala b/src/utils/ByteUtils.scala index 2c51917..18942c0 100644 --- a/src/utils/ByteUtils.scala +++ b/src/utils/ByteUtils.scala @@ -1,6 +1,7 @@ package ixee.cryptopals.utils import FunctionUtils.tup +import ConversionUtils._ object ByteUtils { trait SizedNumeric[T] { @@ -9,8 +10,8 @@ object ByteUtils { def bitSize: Int def fromLong(l: Long): T def toLong(l: T): Long - def buildFrom[U : SizedNumeric](from: U): T = fromLong(from.toLong) - def truncate[U : SizedNumeric](from: U): T = buildFrom(from) + def buildFrom[U : SizedNumeric : BitOps](from: U): T = fromLong(from.toLong) + def truncate[U : SizedNumeric : BitOps](from: U): T = buildFrom(from) override def toString = s"SizedNumeric[${manifest}]" } @@ -21,6 +22,7 @@ object ByteUtils { def @&(a: T, b: T): T def @^(a: T, b: T): T def @+(a: T, b: T): T + def @-(a: T, b: T): T } implicit val byteOps: BitOps[Byte] = new BitOps[Byte] { @@ -30,6 +32,7 @@ object ByteUtils { def @&(a: Byte, b: Byte): Byte = (a & b).toByte def @^(a: Byte, b: Byte): Byte = (a ^ b).toByte def @+(a: Byte, b: Byte): Byte = (a + b).toByte + def @-(a: Byte, b: Byte): Byte = (a - b).toByte } implicit val intOps: BitOps[Int] = new BitOps[Int] { @@ -39,6 +42,7 @@ object ByteUtils { def @&(a: Int, b: Int): Int = a & b def @^(a: Int, b: Int): Int = a ^ b def @+(a: Int, b: Int): Int = a + b + def @-(a: Int, b: Int): Int = a - b } implicit class WithBitOpts[T : BitOps](x: T) { @@ -48,9 +52,10 @@ object ByteUtils { def @&(b: T): T = implicitly[BitOps[T]].@&(x, b) def @^(b: T): T = implicitly[BitOps[T]].@^(x, b) def @+(b: T): T = implicitly[BitOps[T]].@+(x, b) + def @-(b: T): T = implicitly[BitOps[T]].@-(x, b) } - implicit class SizedWithByteInfo[T : SizedNumeric](x: T) { + implicit class SizedWithByteInfo[T : SizedNumeric : BitOps](x: T) { def byteSize = implicitly[SizedNumeric[T]].byteSize def octetSize = byteSize * 2 def bitSize = implicitly[SizedNumeric[T]].bitSize @@ -65,6 +70,17 @@ object ByteUtils { uSize.buildFrom(x) } def hex: String = s"%0${octetSize}x" format x + def bitsSet: Int = { + var bits = 0 + var num = x + + while (num.toLong > 0) { + bits = bits + 1 + num = num @& (num @- 1.truncatedTo[T]) + } + + bits + } def truncatedTo[U : SizedNumeric]: U = { implicitly[SizedNumeric[U]].truncate(x) } @@ -82,8 +98,14 @@ object ByteUtils { implicit val shortized = sizedNumeric(2) { x: Long => x.toShort } { _.toLong } implicit val byteSized = sizedNumeric(1) { x: Long => x.toByte } { _.toLong } - implicit class SeqByteOps(seq: Seq[Byte]) { - def xor(other: Seq[Byte]): Seq[Byte] = + implicit class SeqByteOps[T : SizedNumeric : BitOps](seq: Seq[T]) { + def xor(other: Seq[T]): Seq[T] = seq.zip(other).map(tup(_ @^ _)) } + + def hammingDistance(a: String, b: String): Int = + hammingDistance(a.asBytes, b.asBytes) + + def hammingDistance[T : BitOps : SizedNumeric](a: Seq[T], b: Seq[T]): Int = + (a xor b).map(_.bitsSet).reduce(_ @+ _) } -- cgit v1.1