[SWEA-d2]1979. 어디에 단어가 들어갈 수 있을까

iamjinseo·2022년 10월 27일
0

문제풀이-Python

목록 보기
123/134

https://swexpertacademy.com/main/solvingProblem/solvingProblem.do

문제 설명

N X N 크기의 단어 퍼즐을 만들려고 한다. 입력으로 단어 퍼즐의 모양이 주어진다.

주어진 퍼즐 모양에서 특정 길이 K를 갖는 단어가 들어갈 수 있는 자리의 수를 출력하는 프로그램을 작성하라.

[예제]

N = 5, K = 3 이고, 퍼즐의 모양이 아래 그림과 같이 주어졌을 때

길이가 3 인 단어가 들어갈 수 있는 자리는 2 곳(가로 1번, 가로 4번)이 된다.

[제약 사항]

  1. N은 5 이상 15 이하의 정수이다. (5 ≤ N ≤ 15)

  2. K는 2 이상 N 이하의 정수이다. (2 ≤ K ≤ N)

[입력]

입력은 첫 줄에 총 테스트 케이스의 개수 T가 온다.

다음 줄부터 각 테스트 케이스가 주어진다.

테스트 케이스의 첫 번째 줄에는 단어 퍼즐의 가로, 세로 길이 N 과, 단어의 길이 K 가 주어진다.

테스트 케이스의 두 번째 줄부터 퍼즐의 모양이 2차원 정보로 주어진다.

퍼즐의 각 셀 중, 흰색 부분은 1, 검은색 부분은 0 으로 주어진다.

[출력]

테스트 케이스 t에 대한 결과는 “#t”을 찍고, 한 칸 띄고, 정답을 출력한다.

(t는 테스트 케이스의 번호를 의미하며 1부터 시작한다.)
입력

10
5 3
0 0 1 1 1
1 1 1 1 0
0 0 1 0 0
0 1 1 1 1
1 1 1 0 1
5 3
1 0 0 1 0
1 1 0 1 1
1 0 1 1 1
0 1 1 0 1
0 1 1 1 0
…

출력

#1 2
#2 6
...

첫 시도

t = int(input())
for i in range(1, t + 1):
    res = 0
    l, k = map(int, input().split())  # 크기와 자리수
    _map = [input().replace(" ", "") for _ in range(l)]  # 입력받는 퍼즐

    for m in _map:
        if "1" * k in m.split("0"):
            res += 1

    #전치행렬 만들때 list(zip(*행렬))
    for m in list(zip(*_map)):
        if "1" * k in "".join(m).split("0"):
            res += 1

    print(f"#{i} {res}")

처음에 입력받은 _map에서 공백을 제거하는 데 꽤 애좀 썼다..(공백을 제거 안하면 세로길이의 k를 찾기 위해 행렬을 반전할 때 공백이 들어가기 때문)

문자열에서 공백을 제거할 때는 replace()를 이용하면 된다. => 문자열.replace(" ", "")

또한 zip을 이용해 전치행렬을 만들 수 있다. (참고)

zip(*행렬)

예를들어 [[1,2,3],[4,5,6]]과 같은 행렬이 있을 때 *로 언패킹하면 (1,2,3)(4,5,6)이 나온다. 이를 zip()으로 묶어주니 (1,4), (2,5), (3,6)이 나오는 것!

결과

한시간동안이나 풀었는데 결국....

남의 코드

t = int(input())
 
for tc in range(1, t + 1) :
    n, k = map(int, input().split())
    data = [list(map(int, input().split())) for _ in range(n)]
 
    result = 0
    # 가로 확인
    for i in range(n) :
        cnt = 0
        for j in range(n) :
            if data[i][j] == 1 :
                cnt += 1
            if data[i][j] == 0 or j == n -1 :
                if cnt == k :
                    result += 1
                if data[i][j] == 0 :
                    cnt = 0
 
    # 세로 확인
    for i in range(n) :
        cnt = 0
        for j in range(n) :
            if data[j][i] == 1 :
                cnt += 1
            if data[j][i] == 0 or j == n - 1 :
                if cnt == k :
                    result += 1
                if data[j][i] == 0 :
                    cnt = 0
 
    print('#%d %d' % (tc, result))

https://unie2.tistory.com/1001
한줄을 모두 검사하면서 1을 만나면 카운트를 높이고 0을 만나거나 마지막 열일 때 1이 k개수만큼 있으면 결과+1, 0을 만났으면 카운트를 날려버린다.

전치행렬에서 똑같이 검사한다.


후기


5번 7번 9번 테스트케이스에서 오류가 난다...

그런데 댓글 안보고 애초에 저렇게 한건데 왜 안되지?

+)input output분석해봤는데 zip이 행 순서에 맞게 제대로 안됨..
역시 하드코딩이 최고다..;

1028 ++) 순서에 맞게 안된 게 아니라 "1"*k가 있는지 탐색 후 res를 1번만 카운트하니까 그 꼴이 난 것이다!!
각 행의 문자열을 0으로 split한 후 거기에 "1"*k가 몇 개 있는지 탐색해야함

풀이2

t = int(input())
for i in range(1, t + 1):
    res = 0
    l, k = map(int, input().split())  # 크기와 자리수
    _map = [input().replace(" ", "") for _ in range(l)]  # 입력받는 퍼즐

    for r in _map:
        for m in r.split("0"):
            if m == "1" * k:
                res += 1

    # 전치행렬 만들때 list(zip(*행렬))
    for r in list(zip(*_map)):
        for m in "".join(r).split("0"):
            if m == "1" * k:
                res += 1

    print(f"#{i} {res}")

첫 번째 시도에서 오류를 다듬은 코드이다.
어쨌거나 저쨌거나 삼중반복문인건 변하지 않는군

profile
일단 뭐라도 해보는 중

0개의 댓글