source: http://capturetheswag.blogspot.co.id/2015/12/seccon-2015-nonogram-300-
point.html
57
Problem ini adalah nonogram yaitu tipe puzzle angka dari Jepang. Isi box berdasarkan nomor pada baris dan kolom dan akhirnya akan tampil gambar. Implementasi nonogram pada seccon dapat dilihat pada gambar berikut ini
Untuk menyelesaikan puzzle ini digunakan bantuan nonogram solver berikut ini
http://www.hakank.org/constraint_programming_blog/2010/11/google_cp_solver_a_much_faster_ nonogram_solver_using_defaultsearch.html #!/usr/bin/python # * coding: utf8 * import requests import re
from itertools import izip import PIL
from PIL import ImageFont,Image,ImageDraw import subprocess
import sys
86
URL = 'http://qrlogic.pwn.seccon.jp:10080/game/' #
# Make a transition (automaton) list of tuples from a # single pattern, e.g. [3,2,1]
#
def make_transition_tuples(pattern): p_len = len(pattern)
num_states = p_len + sum(pattern) tuples = []
# this is for handling 0clues. It generates # just the minimal state
if num_states == 0: tuples.append((1, 0, 1)) return (tuples, 1)
# convert pattern to a 0/1 pattern for easy handling of # the states
tmp = [0] c = 0
for pattern_index in range(p_len): tmp.extend([1] * pattern[pattern_index]) tmp.append(0) for i in range(num_states): state = i + 1 if tmp[i] == 0: tuples.append((state, 0, state)) tuples.append((state, 1, state + 1)) else: if i < num_states 1: if tmp[i + 1] == 1: tuples.append((state, 1, state + 1)) else: tuples.append((state, 0, state + 1)) tuples.append((num_states, 0, num_states)) return (tuples, num_states)
#
# check each rule by creating an automaton and transition constraint. #
def check_rule(rules, y):
cleaned_rule = [rules[i] for i in range(len(rules)) if rules[i] > 0] (transition_tuples, last_state) = make_transition_tuples(cleaned_rule) initial_state = 1 accepting_states = [last_state] solver = y[0].solver() solver.Add(solver.TransitionConstraint(y, transition_tuples, initial_state, accepting_states))
def silly(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules): font = ImageFont.truetype('clacon.ttf')
img = Image.new("RGBA", (300,1500),(255,255,255)) draw = ImageDraw.Draw(img)
87
# Create the solver.
solver = pywrapcp.Solver('Nonogram') # # variables # board = {} for i in range(rows): for j in range(cols):
board[i, j] = solver.IntVar(0, 1, 'board[%i, %i]' % (i, j)) board_flat = [board[i, j] for i in range(rows) for j in range(cols)] # Flattened board for labeling.
# This labeling was inspired by a suggestion from # Pascal Van Hentenryck about my (hakank's) Comet # nonogram model.
board_label = []
if rows * row_rule_len < cols * col_rule_len: for i in range(rows): for j in range(cols): board_label.append(board[i, j]) else: for j in range(cols): for i in range(rows): board_label.append(board[i, j]) # # constraints # for i in range(rows):
check_rule(row_rules[i], [board[i, j] for j in range(cols)]) for j in range(cols):
check_rule(col_rules[j], [board[i, j] for i in range(rows)]) #
# solution and search # parameters = pywrapcp.DefaultPhaseParameters() parameters.heuristic_period = 200000 db = solver.DefaultPhase(board_label, parameters) solver.NewSearch(db) num_solutions = 0 while solver.NextSolution(): num_solutions += 1 for i in range(rows):
row = [board[i, j].Value() for j in range(cols)] row_pres = [] for j in row: if j == 1: row_pres.append('█') else: row_pres.append(' ') outline = ''.join(row_pres) outline = unicode(outline,"utf8") width, height = font.getsize(outline)
draw.text((0,y_text),outline,(0,0,0),font=font) y_text += height
88 draw.text((0,y_text)," ",(0,0,0),font=font) y_text += height draw.text((0,y_text)," ",(0,0,0),font=font) y_text += height draw.text((0,y_text)," ",(0,0,0),font=font) y_text += height if num_solutions >= 6: break solver.EndSearch() img = img.resize((700,2000)) img.show() def mainloop(answer): if answer:
print "[*] Posting result: " + answer payload = { 'ans' : answer }
r = s.post(URL, data=payload) else:
print "[*] Using GET Method to get first challenge..." r = s.get(URL)
toprow = [] firstcolumn = []
for line in r.content.splitlines(): if 'Stage:' in line:
thestage = line.split(" ")[1]
print "[*] Stage: " + thestage + " / 30" if '<th class="cols">' in line:
headerblocks = line.split("</th>") p = re.compile("<span>(.*?)</span>") for block in headerblocks:
columnnums = []
if '<th class="rows">' in block: break
subblocks = block.split("<br />") for subblock in subblocks: m = p.search(subblock) if m: columnnums.append(int(m.group(1),10)) if len(columnnums) > 0: toprow.append(columnnums) if '<th class="rows">' in line: if '<th class="cols">' in line:
line = line.split('<th class="rows">')[1] headerblocks = line.split("</th>") p = re.compile("<span>(.*?)</span>") for block in headerblocks:
columnnums = []
subblocks = block.split(" ") for subblock in subblocks: m = p.search(subblock) if m:
columnnums.append(int(m.group(1),10))
89
firstcolumn.append(columnnums)
# hacked together since the Google CP engine needs more than the old engine rulelen = 0
for x in toprow:
if len(x) > rulelen: rulelen = len(x) # zero pad the rules
for x in toprow: while len(x) < rulelen: x.insert(0,0)
rulelen2 = 0
for x in firstcolumn: if len(x) > rulelen2: rulelen2 = len(x) # zero pad the rules
for x in firstcolumn: while len(x) < rulelen2: x.insert(0,0)
silly(len(firstcolumn), rulelen, firstcolumn, len(toprow), rulelen2, toprow) s = requests.Session() ans = "" # super ugly while(1): mainloop(ans) try: thedata = subprocess.check_output(["zbarimg q /tmp/tmp*"],shell=True).split(":")[1].strip().splitlines()[0] except: thedata = ""
print "[*] Decoded QR: " + thedata if thedata == "":
# maybe try and scan it on your phone or something :P ans = raw_input("Enter QR Code result> ")
else: ans = thedata try: subprocess.check_output(["killall","9","display"]) except: pass
Ketika program dirun output yang dihasilkan adalah
# ./pgame2.py
[*] Using GET Method to get first challenge... [*] Stage: 1 / 30
[02:14:26] src/constraint_solver/default_search.cc:1307: Init impact based search phase on 441 variables, initialization splits = 100, heuristic_period = 200000, run_all_heuristics = 1, restart_log_size = 1
[02:14:26] src/constraint_solver/default_search.cc:471: initial log2(SearchSpace) = 50 [02:14:26] src/constraint_solver/default_search.cc:526: init done, time = 2 ms, 14 values removed, log2(SearchSpace) = 36
90
[*] Decoded QR: JkhM3JiP6dU Killed
[*] Posting result: JkhM3JiP6dU [*] Stage: 2 / 30
[02:14:27] src/constraint_solver/default_search.cc:1307: Init impact based search phase on 441 variables, initialization splits = 100, heuristic_period = 200000, run_all_heuristics = 1, restart_log_size = 1
[02:14:27] src/constraint_solver/default_search.cc:471: initial log2(SearchSpace) = 26 [02:14:27] src/constraint_solver/default_search.cc:526: init done, time = 0 ms, 2 values removed, log2(SearchSpace) = 24
[*] Decoded QR: yUNXAQa1421B Killed
[*] Posting result: yUNXAQa1421B [*] Stage: 3 / 30
[02:14:28] src/constraint_solver/default_search.cc:1307: Init impact based search phase on 441 variables, initialization splits = 100, heuristic_period = 200000, run_all_heuristics = 1, restart_log_size = 1
[02:14:28] src/constraint_solver/default_search.cc:471: initial log2(SearchSpace) = 31 [02:14:28] src/constraint_solver/default_search.cc:526: init done, time = 0 ms, 3 values removed, log2(SearchSpace) = 28
[*] Decoded QR: fHOFYusdRKYlN [*] Posting result: fHOFYusdRKYlN Killed
[*] Stage: 4 / 30
[02:14:28] src/constraint_solver/default_search.cc:1307: Init impact based search phase on 441 variables, initialization splits = 100, heuristic_period = 200000, run_all_heuristics = 1, restart_log_size = 1
[02:14:28] src/constraint_solver/default_search.cc:471: initial log2(SearchSpace) = 46 [02:14:28] src/constraint_solver/default_search.cc:526: init done, time = 1 ms, 1 values removed, log2(SearchSpace) = 45
[*] Decoded QR: eQS2SwyUa56wWN [*] Posting result: eQS2SwyUa56wWN Killed
[*] Stage: 5 / 30
[*] Decoded QR: k94Lgdg4lEtnezi [*] Posting result: k94Lgdg4lEtnezi Killed
...
[*] Stage: 29 / 30
[*] Decoded QR: oELkD87acQsH299lL4ajOgUPqh0dy5LW7g474S0 [*] Posting result: oELkD87acQsH299lL4ajOgUPqh0dy5LW7g474S0 Killed
[*] Stage: 30 / 30
[02:20:43] src/constraint_solver/default_search.cc:1307: Init impact based search phase on 1089 variables, initialization splits = 100, heuristic_period = 200000, run_all_heuristics = 1, restart_log_size = 1
[02:20:43] src/constraint_solver/default_search.cc:471: initial log2(SearchSpace) = 79 [02:20:43] src/constraint_solver/default_search.cc:526: init done, time = 2 ms, 11 values removed, log2(SearchSpace) = 68
[*] Decoded QR: SECCON{YES_WE_REALLY_LOVE_QR_CODE_BECAUSE_OF_ITS_CLEVER_DESIGN}
91