coding test

[파이썬] 5120. 암호

잔망루피 2021. 2. 1. 21:50

※ SW Expert 아카데미의 문제를 무단 복제하는 것을 금지합니다.


A사는 창립기념일 이벤트로 비밀번호 맞추기 대회를 열어, 최대 10개인 비밀번호를 맞추는 사람에게 기념품을 제공하기로 했다.

기념품을 받을 수 있도록 다음 조건에 맞는 비밀번호 찾기 프로그램을 작성하시오.

- 1000이하의 숫자 N개가 주어진다. 이때 시작 숫자가 정해지고, 첫 번째 지정 위치가 된다.

- 지정 위치부터 M번째 칸을 추가한다. 여기에 앞칸의 숫자와 뒤로 밀려난 칸의 숫자를 더해 넣는다. 추가된 칸이 새로운 지정 위치가 된다. 밀려난 칸이 없으면 시작 숫자와 더한다.

- 이 작업을 K회 반복하는데, M칸 전에 마지막 숫자에 이르면 남은 칸수는 시작 숫자부터 이어간다.

- 마지막 숫자부터 역순으로 숫자를 출력하면 비밀번호가 된다. 숫자가 10개 이상인 경우 10개까지만 출력한다.



다음은 N, M, K가 6, 3, 3이고, 주어진 숫자가 6, 2, 4, 9, 1, 5인 경우의 예이다. 6이 시작 숫자이자 첫번째 지정 위치가 된다.
 

6

2

4

9

1

5


(1) 3번째에 새로운 칸을 추가하고, 앞의 숫자 4와 뒤로 밀려난 9를 더해 칸을 채운다.
 

6

2

4

 

9

1

5

 

6

2

4

13

9

1

5



(2) 다시 3칸 뒤에 새로운 칸을 추가하고, 앞 뒤 숫자를 더해 넣는다.
 

6

2

4

13

9

1

 

5

 

6

2

4

13

9

1

6

5



(3) 다시 3칸 뒤에 칸을 추가하고 앞 뒤 숫자를 더해 넣는다.
 

6

 

2

4

13

9

1

6

5

 


 

6

8

2

4

13

9

1

6

5




암호는 역순인 5 6 1 9 13 4 2 8 6이 된다.


[입력]

첫 줄에 테스트케이스의 수 T가 주어진다. 1<=T<=50

다음 줄부터 테스트 케이스의 별로 첫 줄에 N, M, K가, 다음 줄에 1000이하의 자연수 N개가 주어진다. 3<=N, M, K<=1000

[출력]

각 줄마다 "#T" (T는 테스트 케이스 번호)를 출력한 뒤, 답을 출력한다.

입력 출력
3
6 3 3
6 2 4 9 1 5
5 3 5
958 386 329 169 778
10 4 10
158 606 636 941 686 774 302 375 954 668
#1 5 6 1 9 13 4 2 8 6
#2 1736 2514 778 169 667 498 329 715 386 958
#3 826 1494 668 954 375 1052 677 302 774 2234

 

🎀 나의 풀이

 

#실패
T = int(input())
# 여러개의 테스트 케이스가 주어지므로, 각각을 처리합니다.
for test_case in range(1, T + 1):
    N, M, K=map(int, input().split())
    num=list(map(int, input().split()))
    #start=num.index(N)
    start=0
    for _ in range(K) :
        idx=start+M
        length=len(num)
        i = idx % length
        pre=num[i-1]
        post=num[i]
        if i == length :
            num.append(pre+post)
        else:
            num.insert(i, pre+post)
        start=i
    print(num)
    print("#%d" %test_case, end=' ')
    
    for i in num[:-11:-1] :    
        print(i, end=' ')
    print()

 

%연산자를 사용했다.

인덱스가 리스트의 길이와 같을 때 맨끝이 아닌 인덱스0에 insert하는 문제가 있다.

2번째 테스트케이스 실행결과 1736 778 169 667 498 827 329 715 386 958이 나왔다.

왜 2번째 자리에 2514가 없고 827이 뜬금없이 있는지 디버그해봤다.

%연산자를 이용한 계산은

len=7, idx=9일 때 i=2

len=8, idx=12일 때 i=4가 된다.

i=5가 나와야함.

따라서 인덱스 범위가 리스트 길이보다 커지면 % 대신에 빼기를 사용해야한다.

 

🎀 다른사람 풀이

 

# 암호
for t in range(1, int(input())+1):
  # 숫자 N개, M번째칸 추가, K회 반복
  N, M, K = map(int, input().split())
  linked_lisd=list(map(int, input().split()))
  index=0
  for i in range(K):
    index+=M
    # 크기가 길이를 넘어가면 길이만큼 빼기
    if index > len(linked_lisd):
      index-=len(linked_lisd)
    # 위치가 0일 경우
    if not index :
      linked_lisd.insert(0, linked_lisd[-1] + linked_lisd[0])
    # 길이 위치에 있다면 제일 마지막에 추가
    elif index == len(linked_lisd):
      linked_lisd.append(linked_lisd[-1] + linked_lisd[0])
    # 평범한 경우
    else : linked_lisd.insert(index, linked_lisd[index-1]+linked_lisd[index])
  #10개가 최대이므로 끊어서 뒤집어준다.
  result=reversed(linked_lisd[-10:])
  print("#{} ".format(t), end='')
  print(*result)
  

 

문제를 잘못 이해했다. N이 시작 숫자인줄 알고 리스트에서 위치를 찾고 시작했었네..

1. 크기가 길이를 넘어갈 때 2. 위치가 0일 때 3. 길이 위치에 있을 때를 고려한다.

의문 : 시작 숫자가 변수에 할당되어 있지 않아서 변할 수도 있는데 ??

 

class Node :
  def __init__(self, data) :
    self.data=data
    self.link=None

class LinkedList:
  def __init__(self) :
    new_node=Node('head')
    self.head=new_node
    self.tail=new_node

    self.before=None
    self.current=None

    self.num_of_data=0

  def append(self, data):
    new_node=Node(data)
    self.tail.link=new_node
    self.tail=new_node
    self.tail.link=self.head.link # 첫 요소와 끝을 연결
    self.num_of_data+=1

  def first(self):
    self.current=self.head.link
    self.before=self.tail
    return self.current.data

  def next(self) :
    self.before = self.current
    self.current=self.current.link
    return self.current.data

  def insert(self, data) :
    new_node=Node(data)
    self.before.link=new_node
    new_node.link=self.current
    self.current=new_node   # current 갱신
    self.num_of_data += 1

  def my_func(self, D) :
    for _ in range(D) :
      self.next()
    num=self.before.data + self.current.data
    self.insert(num)

  def my_result(self):
    lst=[self.first()]
    for _ in range(self.num_of_data-1):
      lst.append(self.next())
    # 마지막 10자리까지 출력
    return ' '.join(map(str, lst[-1:-11:-1]))

T=int(input())
for test_case in range(1, 1+T) :
  N, M, K=map(int, input().split())
  Seq=LinkedList()
  for i in map(int, input().split()):
    Seq.append(i)
  Seq.first()
  for _ in range(K):
    Seq.my_func(M)
  print("#{} {}".format(test_case, Seq.my_result()))

 

1. 클래스 LinkedList내 __init__ 메서드 실행

2. 클래스 Node내 __init__ 메서드 실행

3. append 메서드 실행

4. 클래스 Node내 __init__ 메서드 실행

5. first 메서드 실행

6. my_func 메서드 실행

7. next 메서드 실행

8. insert 메서드 실행

9. 클래스 Node내 __init__ 메서드 실행

 

def crypto(pwd) :
  pivot = 0
  start_num = pwd[pivot]

  for _ in range(1, K+1) :
    pivot+=M

    if pivot > len(pwd) :
      pivot -= len(pwd)

    if pivot == len(pwd) :
      pwd.append(pwd[-1]+ start_num)
    else:
      pwd.insert(pivot, pwd[pivot-1]+pwd[pivot])
  return pwd

T=int(input())

for test_case in range(1, T+1) :
  N, M, K = map(int, input().split())
  password=list(map(int, input().split()))

  encrypted=list(reversed(crypto(password)))

  print(f'#{test_case}', end=' ')
  print(*encrypted[:10])

 

pivot이 리스트 길이보다 클 때, pivot에서 pwd길이를 뺀다.

pivot이 리스트 길이와 같을 때 리스트의 마지막 값과 처음 값을 더하고 맨끝에 이 값을 추가한다. 

반응형

'coding test' 카테고리의 다른 글

[파이썬] 5174. subtree  (0) 2021.02.04
[파이썬] 5122. 수열 편집  (0) 2021.02.03
[파이썬] 5110. 수열 합치기  (0) 2021.01.29
[파이썬] 5108. 숫자 추가  (0) 2021.01.29
[파이썬] 5102. 노드의 거리  (0) 2021.01.27