Python Challenge[32]

[Level 32]

Python Challenge[32]_第1张图片

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

你可能感兴趣的:(Python Challenge[32])