TeamH4C

[빡공팟 5기] W1 ~ W3 : 파이썬 기초 100제 중 5문제 블로깅 과제

이유갬 2022. 10. 10. 19:14

문제를 잘 읽고 개념만 잘 익히면 대부분의 문제를 다 풀 수 있을 정도의 난이도였지만

사소한 거 하나를 빠뜨려 오래 걸렸던 문제, 개념이 잘 잡혀있지 않았던 문제 위주로 블로깅함.

 

81번

 

A, B, C, D, E, F 중 하나가 입력될 때,
1부터 F까지 곱한 16진수 구구단의 내용을 출력해보자.
(단, A ~ F 까지만 입력된다.)

 

입력

16진수로 한 자리 수가 입력된다.단, A ~ F 까지만 입력된다.

 

출력

입력된 16진수에 1~F까지 순서대로 곱한, 16진수 구구단을 줄을 바꿔 출력한다.계산 결과도 16진수로 출력해야 한다.

 

Logic

1. 16진수로 한 자리 수를 입력받는다.2. 입력된 16진수에 1~F까지 순서대로 곱하고 줄을 바꿔 출력한다.3. 계산 결과도 16진수로 출력해야함.

 

사실 이 문제는 알고보면 전혀 어려운 문제가 아닌데처음 문제를 읽고 16진수라고 하니까 어렵게 생각한게 문제였다.

사실 저번 학기때 16진수를 친구한테 맞으면서 배웠다^^ 


내가 제시한 오답 코드

 

n = int(input(), 16)

for i in range(1, 16):
    a = hex(i)
    print("%X"%n, "*%X"%i, "=%X"%(n*a), sep='')

입력 :

B

출력 결과 :

< 아무것도 안나옴 >

 

정말 수치스러운 결과..

이때, 무슨 생각으로 저런 코드를 짰냐면

16진수끼리 곱해야되는 줄 알았다, 그래서 i 를 16진수로 바꿔서 그걸 곱했는데

이게 16진수도 결국 그냥 수를 0 .. 9 A B C D .. F 로 표현한것인데

그냥 계산하고 출력만 16진수로 했으면 됐었다


내가 제시한 정답 코드

 

n = int(input(), 16)

for i in range(1, 16):
    print('%X'%n, '*%X'%i, '=%X'%(n*i), sep='')

 

16진수로 입력을 받고, i 가 순서대로 1 부터 15까지 증가하는 for 문을 이용하여 구구단을 출력했다.

이때, sep='' 는 출력 문자들 간의 공백이 없게 출력하게 해준다.


82번

 

문제 : 친구들과 함께 3 6 9 게임을 하던 영일이는 잦은 실수 때문에 계속해서 벌칙을 받게 되었다.
3 6 9 게임의 왕이 되기 위한 369 마스터 프로그램을 작성해 보자.

입력

30보다 작은 정수 1개가 입력된다. (1 ~ 29)

 

출력

1부터 그 수까지 순서대로 공백을 두고 수를 출력하는데,

3 또는 6 또는 9가 포함 되어있는 수인 경우, 그 수 대신 영문 대문자 X 를 출력한다.

 

Logic

1. 30보다 작은 정수 1개를 입력 받는다.

2. 1부터 입력 받은 수까지 공백을 두고 수를 출력한다.

3. 조건 : 3 or 6 or 9 가 포함되어 있는 수이면 X 를 출력한다.

 

 


내가 제시한 오답 코드 1

 

n = int(input()) // 1 ~ 29 사이의 정수를 입력받음.

for i in range(1, 30):
    print(i, end='')
    if i%10 == 3 or i%10 == 6 or i%10 == 9:
        print("X", end='')

입력 :

9
출력 결과 :
123X456X789X10111213X141516X171819X20212223X242526X272829X

 

엄청 엉망진창으로 풀었음 ㅎㅎ.. 졸면서 풀었나..

1. 1부터 입력 받은 수까지 증가하는 것인데 for i in range(1, 30) 으로 입력한게 첫번째 오답의 이유

2. 공백을 두고 출력해야하는데 end='' 라고 한 것이 두번째 오답의 이유

3. 반복실행문과 조건문 로직 자체의 오류.

코드를 짤 때 이대로 가면 실행 과정이 어떤 식으로 진행되는지 분석을 해야하는데 그것이 부족했음.

123X456X ... 로 나오는 이유는 print 문이 조건문에 앞서서 순서대로 실행되는 걸 간과했음.


내가 제시한 오답 코드 2

n = int(input())

for i in range(1, n+1):
    if i%10 == 3:
        print("X", end=' ')
    elif i%10 == 6:
        print("X", end=' ')
    elif i%10 == 9:
        print("X", end=' ')
    print(i, end=' ')

입력 :

9
출력 결과 :
1 2 X 3 4 5 X 6 7 8 X 9 

 

내가 제시한 오답 코드 1 과 마찬가지로 로직을 잘못 짰는데 정답과 거의 가까워졌음.

1. 앞선 것과 마찬가지로 3, 6, 9를 출력하지 않아야하는데 X 를 먼저 출력하고 3, 6, 9를 그대로 출력한 것이 오답의 이유.

이때, else 가 빠졌다는 것을 인지함. 저 3개의 케이스에 해당되지 않는 나머지 숫자들은 저 조건문을 거치고 그냥 출력될 것이고, 3개의 케이스에 해당이 되면 if 문 안의 실행 코드만 실행하고 넘어가야하는데 else 문이 없으니 그냥 그대로 출력한 거였음.


내가 제시한 정답 코드 1

 

n = int(input())

for i in range(1, n+1):
    if i%10 == 3:
        print("X", end=' ')
    elif i%10 == 6:
        print("X", end=' ')
    elif i%10 == 9:
        print("X", end=' ')
    else:
        print(i, end=' ')

결국 else 문을 삽입하고 성공했음. 하지만 이것보다 더 짧은 코드를 짤 수 있지 않을까? 생각이 들었음.

사실 이렇게 블로깅하다가 첫번째로 제시했던 오답 코드로 더 짧게 작성할 수 있을 거 같아서 다시 짜봤음.

 

내가 제시한 정답 코드 2

 

n = int(input())

for i in range(1, n+1):
    if i%10 == 3 or i%10 == 6 or i%10 == 9:
        print("X", end=' ')
    else:
        print(i, end=' ')

 

 

코드 길이, 실행 시간 다 짧아졌당 ㅎㅎ


90번

 

문제 : 시작 값(a), 곱할 값(m), 더할 값(d), 몇 번째인지를 나타내는 정수(n)가 입력될 때,
n번째 수를 출력하는 프로그램을 만들어보자.

 

입력

시작 값(a), 곱할 값(m), 더할 값(d), 몇 번째 인지를 나타내는 정수(n)가
공백을 두고 입력된다.(a, m, d는 -50 ~ +50, n은 10이하의 자연수)

 

출력

n번째 수를 출력한다.

 

 

Logic

1. a, m, d, n 을 공백을 두고 입력 받는다.

2. 시작값에 m 을 곱하고 d 를 더한 후 n 번째 수를 출력한다.

3. 이때, 시작값이 a1, a2, a3 ... 로 바뀐다는 것을 생각해야한다.

 


내가 제시한 오답 코드

 

a, m, d, n = input().split()

a = int(a)
m = int(m)
d = int(d)
n = int(n)

for i in range(1, n+1):
    a = a * m + d
    
print(a)

입력 :

1 -2 1 8

출력 결과 :

171

정답이 -85가 나와야하는데 왜 171이 나왔는지 한번 출력을 해봤다.

출력 결과 :
-1
3
-5
11
-21
43
-85
171

 

출력 결과를 보니 8번째 수가 171이다. 정답은 그 전의 항 -85가 나와야한다. 왜 이런식으로 되었을까?

여기서 첫번째 항이 이상했다. 시작값은 1이 되어야하는데 -1이 되었다. 1 * -2 + 1 = -1, 첫번째 항이 계산 후 결과가 되어버린것이다.

그렇다면 첫째항은 계산하지 않은 첫째항 그대로 두는 조건을 넣으면 되지 않을까?


내가 제시한 정답 코드

 

a, m, d, n = input().split()

a = int(a)
m = int(m)
d = int(d)
n = int(n)

for i in range(1, n+1):
    if i == 1:
        a = a
    else:
        a = a * m + d

print(a)

 

첫째항을 시작값으로 그대로 두고

그 이후에는 계산한 값을 순서대로 2번째, 3번째, 4번째... 로 두는 코드로 작성했다!

 


94번

 

문제 : 정보 선생님은 오늘도 이상한 출석을 부른다. 
영일이는 오늘도 다른 생각을 해보았다.
출석 번호를 다 부르지는 않은 것 같은데... 가장 빠른 번호가 뭐였지?
출석 번호를 n번 무작위로 불렀을 때, 가장 빠른 번호를 출력해 보자.
단,  첫 번째 번호와 마지막 번호가 몇 번인지는 아무도 모른다. 
음수(-) 번호, 0번 번호도 있을 수 있다. 

입력

번호를 부른 횟수(n, 1 ~ 10000)가 첫 줄에 입력된다.
n개의 랜덤 번호(k)가 두 번째 줄에 공백을 사이에 두고 순서대로 입력된다. 

 

출력

출석을 부른 번호 중에 가장 빠른 번호를 출력한다.

 

Logic

1. 번호를 부른 횟수 n 을 정수형으로 입력 받는다.

2. n 개의 랜덤 번호 k 가 공백을 사이에 두고 순서대로 입력된다.

3. 제일 작은 수는 예측할 수 없으므로(음수일수도 있다고 문제에서 제시함.) 입력 받은 값을 비교 대상으로 만들어야 한다.

 

이 문제는 정답 코드를 보면 크게 어려운 문제는 아니지만

처음 문제를 보았을 때 어떻게 풀어야하나 고민을 많이 했던 문제라 넣었다.

 


내가 제시한 오답 코드

 

n = int(input())
a = list(map(int, input().split))

for i in range(n):
    if a[i] < a[i+1]:
        min = a[i]
    elif i == n-1:
        print(min)
        break
    else:
        continue

 

랜덤 번호를 a 리스트에 띄어쓰기 기준으로 넣어놓고

for 문을 돌려서 a 리스트 안에 존재하는 값들끼리 비교하는 것을 넣었다.

이때, 0 ~ n-1 까지 for 문을 돌렸는데 두 값끼리 비교해서 작은 것은 min 에 대입하고 i 가 n-1 까지인데 이때 첫번째 if 문에서 a[n-1] < a[n]  이 될 수 없기 때문에 elif 문을 넣었는데 사실 무슨 생각으로 저렇게 짰는지 모르겠다..ㅎㅎ


내가 제시한 정답 코드

 

n = int(input())
k = list(map(int, input().split()))

for i in range(n):
    if k[i] <= k[0]:
        k[0] = k[i]
    else:
        continue
    
print(k[0])

 

조금 더 간단하게 생각해보자! 라는 생각으로

맨 처음 원소를 기준으로 비교하면서 작으면 계속 맨 처음 원소로 넣어버리자! 라고 결론을 내렸다.

그렇게 생각하니 코드를 좀 더 쉽게 짤 수 있었다.

처음 원소보다 비교하는 원소가 작거나 같아버리면 처음 원소에 대입해버리고 만약 그렇지 않으면 쭉 n-1 까지 진행하는 것으로 짰다.

그러면 저 반복문이 끝났을 때 맨 처음 원소에 제일 작은 숫자가 올 것이고 따라서 제일 처음 원소를 출력하면 끝나는 것이다.

 


96번

 

문제 : 십자 뒤집기는 
그 위치에 있는 모든 가로줄 돌의 색을 반대(1->0, 0->1)로 바꾼 후,  
다시 그 위치에 있는 모든 세로줄 돌의 색을 반대로 바꾸는 것이다. 
어떤 위치를 골라 집자 뒤집기를 하면, 그 위치를 제외한 가로줄과 세로줄의 색이 모두 반대로 바뀐다. 

바둑판(19 * 19)에 흰 돌(1) 또는 검정 돌(0)이 모두 꽉 채워져 놓여있을 때,
n개의 좌표를 입력받아 십(+)자 뒤집기한 결과를 출력하는 프로그램을 작성해보자.

 

입력

바둑알이 깔려 있는 상황이 19 * 19 크기의 정수값으로 입력된다.
십자 뒤집기 횟수(n)가 입력된다.
십자 뒤집기 좌표가 횟수(n) 만큼 입력된다. 단, n은 10이하의 자연수이다. 

 

출력

십자 뒤집기 결과를 출력한다. 

 

Logic

1. 19 * 19 크기의 2차원 리스트를 입력받는다.

2. 십자 뒤집기 횟수 n 을 입력 받는다.

3. 십자 뒤집기 좌표 x, y 를 입력받고 해당되는 좌표의 바둑돌을 0->1, 1->0 으로 변경한다.

 

정말 역대급으로 오래 걸렸던 문제였다..전부터 항상 배열에 약했는데 공부의 필요성을 절실하게 깨닫게 해준 문제였다.. ㅎㅎ

해당되는 좌표의 바둑돌을 0->1, 1->0 으로 바꾸는 것도 어려웠지만 문제에서 이미 힌트를 주었고

처음부터 19*19 크기의 2차원 리스트를 입력받는 것이 난관이였다.


내가 제시한 오답 코드

 

d = [list(map(int, input().split())) for i in range(1,20)]

for i in range(n): 
  x,y=input().split()
  for j in range(1, 20) :
    if d[j][int(y)]==0 : 
      d[j][int(y)]=1
    else :
      d[j][int(y)]=0

    if d[int(x)][j]==0 :
      d[int(x)][j]=1
    else :
      d[int(x)][j]=0
      
for i in range(1, 20):
    for j in range(1, 20):
        print(d[i][j], end=' ')
    print()

 

2차원 리스트를 출력하는 건 이중 for 문을 돌리면 된다는 것을 알고 있었기 때문에 출력은 어렵지 않았다.

하지만 처음 입력을 받는 것을 어떻게 해야할지 복잡했다.

이것도 이중 for 문을 돌려야하나? 미리 2중 리스트를 만들고 0 이라는 값을 모두 대입한 다음 입력을 받아야하나 그럼 이때 입력 받는 것도 이중 for 문인가? 하면서 머리가 실타래처럼 꼬였다..


내가 제시한 정답 코드

 

d=[]
for i in range(20):
  d.append([])
  for j in range(20): 
    d[i].append(0)

for i in range(19):
  a = input().split()
  for j in range(19):
    d[i+1][j+1] = int(a[j])

n = int(input())

for i in range(n): 
  x,y=input().split()
  for j in range(1, 20):
    if d[j][int(y)]==0: 
      d[j][int(y)]=1
    else :
      d[j][int(y)]=0

    if d[int(x)][j]==0:
      d[int(x)][j]=1
    else :
      d[int(x)][j]=0
      
for i in range(1, 20):
    for j in range(1, 20):
        print(d[i][j], end=' ')
    print()

 

그래서 차근 차근 적어가면서 해보았다.

첫번째, d 라는 빈 리스트를 선언 후에 앞선 문제처럼 리스트 안에 리스트를 추가하였다.

그리고나서 두번째, 입력을 받는다. 이때 입력은 한 줄씩 입력받아서 넣는 것으로 했다.

우선, 첫번째 행에 띄어 쓰기 기준으로 a 라는 리스트에 대입하고, 이를 for 문을 돌려서 1행부터 19행까지 왼쪽에서 오른쪽으로 차근 차근 값을 대입하는 것으로 했다.

풀린 순간 정말 세상이 아름다워보였다.. 이 맛에 코딩을 하나보다..


<파이썬 코드업 기초 100제 올클리어 인증>