yhpg0４ - テトロミノ認識 をPythonで解いてみる


http://nabetani.sakura.ne.jp/hena/ord4tetroid/
で出題されたテトロミノ認識をPythonで解いてみる

全検索して、
ifで図形一つずつ比較していく作戦
ブロックは４つしかない。と決めつけて解いている。

```py:yhpg04.py
#!/usr/bin/env python3
# -*- coding:utf-8 -*-

# https://yhpg.doorkeeper.jp/
# http://nabetani.sakura.ne.jp/hena/ord4tetroid/

def solve(data):

    field = createField(data)
    for i in range(len(field)-1):
        for j in range(len(field[i])-1):
                if isL(field,i,j):
                    return "L"
                elif isI(field,i,j):
                    return "I"
                elif isT(field,i,j):
                    return "T"
                elif isO(field,i,j):
                    return "O"
                elif isS(field,i,j):
                    return "S"
                else:
                    continue

    return "-"

def isL(field,i,j):
    #1,
    #1,
    #1,1
    # or
    #x,1
    #x,1
    #1,1
    if field[i][j] == 1 and field[i+1][j] == 1 and field[i+2][j] == 1 and (field[i+2][j+1] or field[i+2][j-1]):
        return True
    #1,1,1
    #x,x,1
    #or
    #x,x,1
    #1,1,1
    elif field[i][j] == 1 and field[i][j+1] == 1 and field[i][j+2] == 1 and (field[i+1][j+2] or field[i-1][j+2]):
        return True
    #1,1,1
    #1
    #or
    #1,
    #1,1,1
    elif field[i][j] == 1 and field[i][j+1] == 1 and field[i][j+2] == 1 and (field[i+1][j] or field[i-1][j]):
        return True
    #1,1
    #1
    #1
    elif field[i][j] == 1 and field[i+1][j] == 1 and field[i+2][j] == 1 and field[i][j+1]:
        return True
    #1,1
    #x,1
    #x,1
    elif field[i][j] == 1 and field[i][j+1] == 1 and field[i+1][j+1] == 1 and field[i+2][j+1]:
        return True


    return False


def isI(field,i,j):
    #1
    #1
    #1
    #1
    if field[i][j] == 1 and field[i+1][j] == 1 and field[i+2][j] == 1 and field[i+3][j] == 1:
        return True
    #1,1,1,1
    elif field[i][j] == 1 and field[i][j+1] == 1 and field[i][j+2] == 1 and field[i][j+3] == 1:
        return True

    return False

def isT(field,i,j):
    #x,1,
    #1,1,1
    #or
    #1,1,1
    #x,1,
    if field[i][j] == 1 and field[i][j+1] == 1 and field[i][j+2] == 1 and (field[i-1][j+1] == 1 or field[i+1][j+1]):
        return True
    #1,
    #1,1,
    #1,
    #x,1
    #1,1
    #x,1
    elif field[i][j] == 1 and field[i+1][j] == 1 and field[i+2][j] == 1 and (field[i+1][j+1] == 1 or field[i+1][j-1] == 1):
        return True

    return False

def isO(field,i,j):
    #1,1,
    #1,1,
    if field[i][j] == 1 and field[i][j+1] == 1 and field[i+1][j] == 1 and field[i+1][j+1] == 1:
        return True
    return False

def isS(field,i,j):
    #1,
    #1,1
    #x,1
    #or
    #x,1
    #1,1
    #1,
    if field[i][j] == 1 and field[i+1][j] == 1 and ((field[i+1][j+1] == 1 and field[i+2][j+1] == 1) or ( field[i+1][j-1] == 1 and field[i+2][j-1] == 1)):
        return True
    #x,1,1
    #1,1,
    #or
    #1,1,
    #x,1,1
    elif field[i][j] == 1 and field[i][j+1] == 1 and ((field[i+1][j-1] == 1 and field[i+1][j] == 1) or (field[i+1][j+1] == 1 and field[i+1][j+2] == 1)):
        return True
    return False

def createField(data):
    field = [[0 for rows in range(12)] for columns in range(12)]
    dataArray = data.split(",")
    for d in dataArray:
        field[int(d[0],10)+1][int(d[1],10)+1] = 1
    return field

def test(data, expect):
    result = solve(data)
    if result == expect:
        print("成功: " + result + "/" + expect )
    else:
        print("失敗: " + result + "/" + expect )

test("55,55,55,55", "-")
test("39,28,27,29", "L")
test("63,62,43,53", "L");
test("32,42,43,44", "L");
test("81,72,91,71", "L");
test("62,64,72,63", "L");
test("45,25,35,24", "L");
test("12,20,22,21", "L");
test("66,46,67,56", "L");
test("44,46,45,43", "I");
test("04,24,14,34", "I");
test("43,42,41,40", "I");
test("48,38,58,68", "I");
test("31,20,22,21", "T");
test("69,79,78,89", "T");
test("42,33,44,43", "T");
test("16,25,05,15", "T");
test("27,37,28,38", "O");
test("13,24,23,14", "O");
test("63,72,62,73", "O");
test("73,63,62,74", "S");
test("56,57,47,66", "S");
test("88,99,98,87", "S");
test("62,43,52,53", "S");
test("86,95,87,96", "S");
test("84,83,73,94", "S");
test("32,33,41,42", "S");
test("86,85,75,96", "S");
test("97,76,96,77", "-");
test("53,55,45,43", "-");
test("73,93,94,84", "-");
test("31,33,41,42", "-");
test("21,32,11,12", "-");
test("73,75,65,64", "-");
test("64,65,45,54", "-");
test("12,00,01,10", "-");
test("94,85,75,74", "-");
test("87,86,77,75", "-");
test("56,56,56,56", "-");
test("41,42,41,52", "-");
test("61,60,63,61", "-");
test("03,13,33,13", "-");
test("92,96,94,93", "-");
test("15,25,55,45", "-");
test("17,14,16,13", "-");
test("72,83,83,92", "-");
test("40,40,42,51", "-");
test("81,80,93,82", "-");
test("51,61,30,41", "-");
test("17,37,35,15", "-");
```

もうちょっとどうにかならないかと思って考えてみた。
縦と横から１がならんでいる数をかぞえて図形を判断する作戦。
なんとかif文の数を減らしたいなと思ったのだけれど、結果は何も変わらなかった。ふしぎ。
図形がfieldの中に１つしか存在しないとなりたたないのも、最初に書いた奴と変わらない。

```py:yhpg04_02.py
#!/usr/bin/env python3
# -*- coding:utf-8 -*-

# https://yhpg.doorkeeper.jp/
# http://nabetani.sakura.ne.jp/hena/ord4tetroid/

def solve(data):

    field = createField(data)
    pattern = []
    pattern.append(countDuplicate(field))
    pattern.append(countDuplicate(list(zip(*field))))

    if isL(pattern) :
        return "L"
    elif isI(pattern):
        return "I"
    elif isT(pattern):
        return "T"
    elif isO(pattern):
        return "O"
    elif isS(pattern):
        return "S"
    else:
        return "-"

def isL(pattern):
    if pattern == [[3, 1], [1, 1, 2]]:
        return True
    elif pattern == [[1, 1, 2], [1, 3]]:
        return True
    elif pattern == [[1, 3], [2, 1, 1]]:
        return True
    elif pattern == [[2, 1, 1], [3, 1]]:
        return True
    elif pattern == [[3, 1], [2, 1, 1]]:
        return True
    elif pattern == [[2, 1, 1], [1, 3]]:
        return True
    elif pattern == [[1, 3], [1, 1, 2]]:
        return True
    elif pattern == [[1, 1, 2], [3, 1]]:
        return True
    else:
        return False

def isI(pattern):
    if pattern == [[4], [1, 1, 1, 1]]:
        return True
    elif pattern == [[1, 1, 1, 1], [4]]:
        return True
    elif pattern == [[4], [1, 1, 1, 1]]:
        return True
    elif pattern == [[1, 1, 1, 1], [4]]:
        return True
    else:
        return False

def isT(pattern):
    if pattern == [[3, 1], [1, 2, 1]]:
        return True
    elif pattern == [[1, 2, 1], [1, 3]]:
        return True
    elif pattern == [[1, 3], [1, 2, 1]]:
        return True
    elif pattern == [[1, 2, 1], [3, 1]]:
        return True
    else:
        return False

def isO(pattern):
    if pattern == [[2, 2], [2, 2]]:
        return True
    else:
        return False

def isS(pattern):
    if pattern == [[2, 2], [1, 2, 1]]:
        return True
    elif pattern == [[1, 2, 1], [2, 2]]:
        return True
    else:
        return False

def countDuplicate(field):
    result = []
    for i in range(len(field)):
        count = 0
        for j in range(len(field[i])):
            if field[i][j] == 1:
                count = countChain(1,field,i,j)
                break
        if(count != 0):
            result.append(count)
    return result

#右方向に自身の数も加えて何個つながっているか数える
def countChain(count,field,i,j):
    if field[i][j+1] == 1:
        count+=1
        return countChain(count, field,i,j+1)
    else:
        return count

def createField(data):
    field = [[0 for rows in range(11)] for columns in range(11)]
    dataArray = data.split(",")
    for d in dataArray:
        field[int(d[0],10)][int(d[1],10)] = 1
    return field
```