파이썬 알고리즘 018 | 곶감(모래시계)*

Yunny.Log ·2021년 1월 8일
0

Algorithm

목록 보기
18/318
post-thumbnail

18. 곶감(모래시계)

현수는 곳감을 만들기 위해 감을 깍아 마당에 말리고 있습니다. 현수의 마당은 N*N 격자판으
로 이루어져 있으며, 현수는 각 격자단위로 말리는 감의 수를 정합니다.
그런데 해의 위치에 따라 특정위치의 감은 잘 마르지 않습니다. 그래서 현수는 격자의 행을
기준으로 왼쪽, 또는 오른쪽으로 회전시켜 위치를 변경해 모든 감이 잘 마르게 합니다.
만약 회전명령 정보가 2 0 3이면 2번째 행을 왼쪽으로 3만큼 아래 그림처럼 회전시키는 명령
입니다.

1행 10 13 10 12 15
2행 12 39 30 23 11
3행 11 25 50 53 15
4행 19 27 29 37 27
5행 19 13 30 13 19

10 13 10 12 15
23 11 12 39 30
11 25 50 53 15
19 27 29 37 27
19 13 30 13 19

첫 번째 수는 행번호, 두 번째 수는 방향인데 0이면 왼쪽, 1이면 오른쪽이고, 세 번째 수는 회
전하는 격자의 수입니다.
M개의 회전명령을 실행하고 난 후 아래와 같이 마당의 모래시계 모양의 영역에는 감 이 총 몇 개가 있는지 출력하는 프로그램을 작성하세요.

10 13 10 12 15
23 11 12 39 30
11 25 50 53 15
19 27 29 37 27
19 13 30 13 19

▣ 입력설명
첫 줄에 자연수 N(3<=N<=20) 이 주어며, N은 홀수입니다.
두 번째 줄부터 N줄에 걸쳐 각 줄에 N개의 자연수가 주어진다.
이 자연수는 각 격자안에 있는 감의 개수이며, 각 격자안의 감의 개수는 100을 넘지 않는다.
그 다음 줄에 회전명령의 개수인 M(1<=M<=10)이 주어지고, 그 다음 줄부터 M개의 회전명령
정보가 M줄에 걸쳐 주어집니다.

▣ 출력설명
총 감의 개수를 출력합니다.

▣ 입력예제 1
5 1
0 13 10 12 15
12 39 30 23 11
11 25 50 53 15
19 27 29 37 27
19 13 30 13 19
3 2
0 3
5 1 2
3 1 4

▣ 출력예제 1
362

<내 풀이>

도저히 회전하는 방법을 모르겠어서 풀지 못했다
밑에 모래 시계 모양으로 나오는 부분만 스스로 해결

sum=0
e=0
s=n-1
for i in range(n) :
    for j in range(e,s+1) :
        sum+=a[i][j]
        print(sum)
    if i<n//2:           #다만 for이 한바퀴 돌고난 후에 s,e증감여부 정해줘야 하므로 띄어쓰기 유의하자
        e+=1
        s-=1
    else : 
        e-=1
        s+=1

<풀이>

n=int(input()) #n*n의 2차리스트, 홀수
a=[list(map(int, input().split())) for _ in range (n)]

m=int(input()) #m개의 회전명령

for i in range(m):
    h, t, k = map(int, input().split())
    if t==0 :
        for _ in range(k) :
            a[h-1].append(a[h-1].pop(0)) #pop하고 뒤에다가 붙여줌
    else :
        for _ in range(k) :
            a[h-1].insert(0, a[h-1].pop()) #맨뒤에 있는 애를 pop해서 

sum=0
e=0
s=n-1
for i in range(n) :
    for j in range(e,s+1) :
        sum+=a[i][j]
    if i<n//2:
        e+=1
        s-=1
    else : 
        e-=1
        s+=1
print(sum)

<다른 분 풀이>

n=int(input())
lst=[list(map(int, input().split())) for _ in range(n)]
m=int(input())


for _ in range(m):
    a,b,c=map(int, input().split())
    if b==0:
        for _ in range(c):
            tmp=lst[a-1][0]
            lst[a-1][:-1]=lst[a-1][1:]
            lst[a-1][-1]=tmp
    else:
        for _ in range(c):
            tmp=lst[a-1][-1]
            lst[a-1][1:]=lst[a-1][:-1]
            lst[a-1][0]=tmp

s=0
e=n
res=0
for i in range(n):
    for j in range(s,e):
        res+=lst[i][j]
    if i<n//2:
        s+=1
        e-=1
    else:
        s-=1
        e+=1
print(res)

<반성점>

  • m=int(input()) #m개의 회전명령
    b=[list(map(int, input().split())) for _ in range (m)]

이렇게 받았었는데 이 회전명령은 각각의 세 숫자들이 쓸모가 각기 있으니깐
저렇게 한꺼번에 받는 것보다

h, t, k=map(int,input().split())
이렇게 받는 것이 더욱 낫다

  • 띄어쓰기 유의하자
for i in range(n) :
    for j in range(e,s+1) :
        sum+=a[i][j]
        print(sum)
    	if i<n//2:           
        	e+=1
        	s-=1
    	else : 
        	e-=1
        	s+=1
 #처음에 이렇게 했더니 첫바퀴 도는 와중에 if~else 가 적용돼서 값이 안나왔었다
  • 여기서 사용된 pop함수나 insert함수를 몰랐던건 아닌데 사용해 보겠다는 생각 자체를 못함
  • 모래시계 모양으로 만드는건 아마 저번에 다이아몬드 모양으로 만드는 걸 안했다면 손도 못댔을 듯

<배운 점>

  • pop을 사용하면 리스트들이 땡겨진다
    (ex) : lst=[0,1,2,3,4] / lst.pop(0) =>[1, 2, 3, 4]
    이 성질을 이용해서 이 문제에서 활용
    그냥 pop()쓴다면 맨 뒤에 있는 것 꺼내오는 거다
    => 이 pop을 append, insert와 함께 쓰는 것이 가능하다

  • 리스트.insert (몇번인덱스, 넣을 값)

  • 리스트의 원소들을 슬라이딩 해야 할 때는 pop/insert를 떠올리자

    lst.pop(): 함수의 인자로 0을 주면 0번 인덱스를 삭제하고 하나씩 왼쪽으로 당긴다. 인자로 공백을 주면 가장 마지막 인덱스를 삭제.
    lst.insert(index, value): 반드시 삽입할 위치를 명시해야 한다. index위치에 삽입되면 그 오른쪽의 원소들이 하나씩 오른쪽으로 밀린다.

  • NxN행렬에서 다이아몬드 모양은 중간에서 시작해서 왼쪽으로는 빼주고 오른쪽으로는 더해주다가 N//2행을 넘어가면 반대로 왼쪽으로 더하고 오른쪽으로 빼준다.

  • NxN행렬에서 모래시계 모양은 각각 처음과 끝에서 시작해서 왼쪽으로는 더해주고 오른쪽으로는 빼주다가 N//2행을 넘어가면 반대로 왼쪽으로 빼고 오른쪽으로 더해준다.

0개의 댓글