Seven-segment Display from codejam

Problem

Tom is a boy whose dream is to become a scientist, he invented a lot in his spare time. He came up with a great idea several days ago: to make a stopwatch by himself! So he bought a seven-segment display immediately.

The seven elements of the display are all light-emitting diodes (LEDs) and can be lit in different combinations to represent the arabic numerals like:

161302_y3n3_922297.png

However, just when he finished the programs and tried to test the stopwatch, some of the LEDs turned out to be broken! Some of the segments can never be lit while others worked fine. So the display kept on producing some ambiguous states all the time...

Tom has recorded a continuous sequence of states which were produced by the display and is curious about whether it is possible to understand what this display was doing. He thinks the first step is to determine the state which the display will show next, could you help him?

Please note that the display works well despite those broken segments, which means that the display will keep on counting down cyclically starting from a certain number (can be any one of 0-9 since we don't know where this record starts from). 'Cyclically' here means that each time when the display reaches 0, it will keep on counting down starting from 9 again.

For convenience, we refer the seven segments of the display by the letters A to G as the picture below:

161546_SCuU_922297.png


基本的想法是:

  1. 先假设所有的节点,都处于不确定的状态(2),根据后续的匹配验证,更新节点的状态,该节点正常为1,不正常为0;

  2. 从9到0(或者从0到9)开始的倒序数列与输入的数列进行匹配验证;

  3. 验证到某个输入时,检查是否出现矛盾;如果出现,那么废弃这次尝试,更新起点,重新验证;如果没有矛盾,更新节点的状态,并继续;

  4. 9 ~ 0,验证完毕后,只产生了一个输出,那么该输出即为结果; 如果出现多于一个的结果,或者,在验证某个序列的时候,最终的节点状态,某个节点仍未知,且该节点要输出1,也表明无法确定结果;


代码如下:

import codejam.FileOp

/**
 * Created by senyuanwang on 15/5/1.
 */
object A1 extends App with FileOp {
  override val filePrefix = "src/main/scala/codejam/year2015/apactest/A-large-practice"

  type LED = List[Int]

  object LED {
    def apply(str: String): LED = (str.toCharArray().map(_ - '0')).toList
  }

  def markMask(a: LED, b: LED, mask: LED): Option[LED] = {
    (a, b, mask) match {
      case (1 :: at, 1 :: bt, 2 :: mt) => markMask(at, bt, mt).map(mask => 1 :: mask) //确认该节点是正常的
      case (1 :: at, 1 :: bt, 1 :: mt) => markMask(at, bt, mt).map(mask => 1 :: mask) //正常case
      case (1 :: at, 1 :: bt, 0 :: mt) => None //已确认损坏的节点被点亮了,和前面的case矛盾
      case (1 :: at, 0 :: bt, _) => None //不该点亮的节点被点亮了
      case (0 :: at, 1 :: bt, 1 :: mt) => None //已确认该节点work的情况下,该节点未点亮
      case (0 :: at, 1 :: bt, _ :: mt) => markMask(at, bt, mt).map(mask => 0 :: mask) //确认该节点是损坏的
      case (0 :: at, 0 :: bt, m :: mt) => markMask(at, bt, mt).map(mask => m :: mask) //无法确认该节点是否损坏
      case (Nil, Nil, Nil) => Some(Nil)
    }
  }

  def light(led: LED, mask: LED): LED =
    (led, mask) match {
      case (1 :: at, 2 :: bt) => throw new Exception("ERROR")
      case (a :: at, b :: bt) => (a & b) :: light(at, bt)
      case _ => Nil
    }

  def solve(input: List[LED], path: List[LED], mask: LED): Option[LED] =
    (input, path) match {
      case (Nil, head :: tail) =>
        Some(light(head, mask))
      case (a :: at, b :: bt) =>
        markMask(a, b, mask).flatMap(solve(at, bt ++ List(b), _))
    }

  val ZERO = LED("1111110")
  val ONE = LED("0110000")
  val TWO = LED("1101101")
  val THREE = LED("1111001")
  val FOUR = LED("0110011")
  val FIVE = LED("1011011")
  val SIX = LED("1011111")
  val SEVEN = LED("1110000")
  val EIGHT = LED("1111111")
  val NINE = LED("1111011")

  val cycle = NINE :: EIGHT :: SEVEN :: SIX :: FIVE :: FOUR :: THREE :: TWO :: ONE :: ZERO :: Nil

  def startCycle(x: Int): List[LED] = {
    val (a, b) = cycle.splitAt(9 - x)
    b ++ a
  }

  def substract(leds: List[LED], list: List[LED], index: Int, result: List[LED]): Option[List[LED]] = {
    (leds, list) match {
      case (Nil, _) => Some(result.reverse)
      case (a :: at, b :: bt) if (index < 10) => substract(at, list, index + 1, a :: result)
      case (a :: at, b :: bt) if a != b => None
      case (a :: at, b :: bt) => substract(at, bt, index + 1, a :: result)
    }
  }

  def process(t: Int): Option[LED] = {
    val line = file.next().split("\\s+")
    val n = line(0).toInt

    val leds =
      (for {
        i <- 1 to n
        led = LED(line(i))
      } yield led).toList
    substract(leds, leds, 0, Nil).flatMap {
      leds =>
        val m = -1
        val mask = LED("2222222")
        try {
          val result = (for {
            i <- 9 to 0 by -1
            led <- solve(leds, startCycle(i), mask)
          } yield led).toSet

          if (result.size != 1) {
            None
          } else {
            Some(result.head)
          }
        } catch {
          case error: Exception => None
        }
    }
  }

  val T = file.next().toInt
  for {
    t <- 1 to T
  } {
    process(t) match {
      case Some(res) => println(s"Case #$t: ${res.mkString}")
      case None => println(s"Case #$t: ERROR!")
    }
  }
}







转载于:https://my.oschina.net/u/922297/blog/408901

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值