Python Challenge[32]

[Level 32]


Title: etch-a-scetch

求解有点复杂,是一个叫 Nonogram 的游戏。

从源码的 warmup.txt 解到 up.txt,再解 up.txt。代码没优化,用时比网上大神的要慢个三倍多吧。

from PIL import Image
import time
def load(file):# 返回hl(len(hor)),vl(len(ver)),hor,ver
  with open(file, encoding='utf-8') as f:
    lines = f.readlines()
    lines = [line.strip() for line in lines if (not line.startswith('#')) and line.strip()!='']
    raw = [list(map(int, line.split())) for line in lines]
    return raw[0][0], raw[0][1], raw[1:raw[0][0] + 1], raw[raw[0][0] + 1:]


def game(hor, ver, hl, vl):# x 表示行,y 表示列。
  hor_alts = [[],] * hl# 用于存储行可能性
  ver_alts = [[],] * vl# 用于存储列可能性
  line = ['-',] * vl# hl 行,vl列
  board = []
  for h in range(hl):
    board.append(line+[])
  dires = [0, 1]# 0 表示水平,1 表示垂直。

  init(hor, hor_alts, dires[0])
  init(ver, ver_alts, dires[1])
  temp_board = []
  count = 0
  print(time.process_time())
  while True:
    rever_map(hor_alts, hl, board, dires[0])
    rever_map(ver_alts, vl, board, dires[1])
    count = count +1
    if count == 15:
      break
  for b in board:
    if '-' in b:
      print('未解决,还应该再改进!')
  return board


def init(hor, alts, d):
  for i, line in enumerate(hor):# Such as line = (2, 1, 3)
    x, d, pos = getData(line, hl)
    alts[i] = []# 需重新开辟空间
    getP(x, d, pos, alts[i])# 获取可能性。(列表)


def rever_map(schemes, length, board, d):
  for i in range(length):
    pss, ass = [], []
    line = getLine(i, board, d)
    getIndex('#', line, pss)
    getIndex('*', line, ass)
    schemes[i] = del_im(pss, ass, schemes[i])# 去除第 i 行/列不可能的备选方案。
    times = getTimes(schemes[i], length)
    if len(schemes[i]) !=0:
      setMap(i, schemes[i], times, board, d)# 将确定的选项写入。


def setMap(i, schemes, times, board, d):# 将确定的选项写入。
  l = len(schemes)
  for j, t in enumerate(times):
    if t == l and d == 1:
      board[j][i] = '#'
    elif t == 0 and d == 1:
      board[j][i] = '*'
    elif t == l and d == 0:
      board[i][j] = '#'
    elif t == 0 and d == 0:
      board[i][j] = '*'
  if l == 1:
    schemes = []


def getLine(i, board, d):# 获取第 i 行/列。
  if d == 0:
    return board[i]
  else:
    return [board[j][i] for j in range(len(board))]


def del_im(pss, ass, scheme):# 去除某行/列不可能的备选方案。
  res = []#最终 scheme = res
  for s in scheme:# scheme 为某一种备选方案。
    flag = True
    for p in pss:
      if s[p] != 1:
        flag = False
        break
    for p in ass:
      if s[p] != 0:
        flag = False
        break
    if flag:
      res.append(s)
  return res


def getTimes(source, l):# 获取所有方案中元素在其各个位置出现次数,如source = [[1, 1, 0, 0], [0, 1, 1, 0]]
  res = [0,] * l# 出现次数。
  for s in source:
    for i in range(l):
      res[i] = res[i] + s[i]
  return res


def getIndex(s, source, res):# 获取所有 s 在 source 中的索引。s 表示要查找的元素,sour 可以是列表、字符串等,res 存储结果。
  t = 0
  while True:
    if s in source[t:]:
      i = source.index(s, t)
      res.append(i)
      t = i + 1
    else:
      break


def getP(x, d, pos, res):# 获取可能性
  if len(pos) == 1:
    d = d + [0,] * x
    res.append(d)
    return
  for m in range(x,-1,-1):
    if m > 0:
      new_d = d[:pos[0]] + [0,] * m + d[pos[0]:]
      new_pos = [p+m for p in pos]
      if x - m > 0:# 剩余可分配0的个数为 x-m 个
        getP(x-m, new_d, new_pos[1:], res)
      elif x - m == 0:# 剩余可分配0的个数为0,完成需要
        res.append(new_d)
    elif m == 0:
      getP(x, d, pos[1:], res)


def getData(data, n):# x 为剩余可用于插入的点,d 为可用于插入的列表,pos 为插入的位置
  d = []
  for i in data:# 转化序列,[2, 1, 3] → [1, 1, 0, 1, 0, 1, 1, 1]
    d = d + [1,] * i + [0]
  d = d[:-1]
  x = n - len(d)
  pos = {0}
  i = 0
  try:
    while True:
      t = d.index(0, i)
      pos.add(t)
      i = t + 1
  except:
    if len(d) > 1:
      pos.add(len(d) - 1)# [0, 2, 4, 7] 零所在位置(2,4)和头尾(0,7)都可用于插入。
  pos = list(pos)
  pos.sort()
  return x, d, pos

def print_board(board):
    for b in board:
        print(''.join(b))

def drawPic(board, x, y):
  img = Image.new('L', (x, y))
  data = []
  for b in board:
    for p in b:
      if p == '#':
        data.append(0)
      else:
        data.append(255)
  img.putdata(data)
  return img


hl, vl, hor, ver = load('up.txt')
board = game(hor, ver, hl, vl)
print_board(board)
print(time.process_time())
img = drawPic(board, vl, hl)
img.resize((100, 100)).show()

得到蛇的图片,Python,从 python.html 最终得到 [Level 33]

Python Challenge Wiki

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容