코딩테스트

[제로베이스] 5월 10일 코딩 테스트 연습 리뷰

scone 2022. 5. 11. 19:39

🥕 1번 전광판에 snowball 띄우기

문제 분석 :

전광판에는 n개만큼의 문자가 띄워진다.

s로 문자열이 주어진다.

ex) 5, snowball이 주어지면
0초 : .....

1초 : ....s

4초 : .snow

6초 : nowba

9초 : ball.

 

내 코드

def solution(n, s, t):
    s = '.'*n+s
    length = len(s)
    t %= length
    if t < length-n:
        ans = ''
        for w in s[t:t+n]:
            ans += w
        return ans
    else:                  
        ans = ''
        for w in s[t:]:
            ans += w
        ans = ans + '.'*(n-len(ans))
        return ans
n = 5
s = "Snowball"
t = 25
print(solution(n,s,t))

[코드해석] :

1. .....snowball 만들어 놓고, slice로 끊었으며

2. 길이를 초과하는 t가 나올 경우, 부족한 수 만큼 '.'을 더해줬다.

3. 가령 all에서 끊기면, 출력은 all.. 로 하는 식

4. 나머지 연산으로 t를 len('.....snowball') 으로 나눠줬기 때문에 일반화가 가능하다.

 

def solution(n, s, t):
# . . . . . s n o w b a l l . . . . .  s n o w b a l l . . . . . s n 
    empty = '.' * n
    word_list = list(empty + s) * n
    result = ''

    for i in word_list[0+t:n+t]:
        result += i

    return result

한석님 코드

 . . . . . s n o w b a l l . . . . .  s n o w b a l l . . . . . s n 

충분히 리스트를 만든 후 이를 슬라이싱 해서 출력하였다.

코딩 테스트에서 짧은 시간 내에 효율적이며 직관적인 코드라고 할 수 있지 않을까

 

def solution(n, s, t): # snowball
    s = s + '.'*n 
    screen = str('.'*n)
    for i in range(t+1):
        if i == 0:
            pass
        screen += s[i%len(s)-1]
        if len(screen) > n:
            screen = screen[1:]
    return screen

재경님 코드

screen 이라는 변수를 따로 만든 후, 시간 t에 따라 스크린 값이 변하는걸 구현하였다.

슬라이싱을 매우 잘 활용한 사례

 

🥕 5번 - ‘-3+26+5’ 등의 문자열이 주어졌을 때, 이를 계산하기

내 코드

def solution(s):
    s = list(s)
    templist = []
    signal = 43
    ans = 0
    for idx,item in enumerate(s):
        if idx == 0 and (ord(item)!=45 and ord(item)!=43):
            templist.append(item)
            continue
        elif idx == 0 :
            signal = ord(item)
            continue
        elif idx == len(s)-1:
            templist.append(item)
            num = int(''.join(map(str, templist)))
            if signal == 45:
                ans -= num

            elif signal == 43:
                ans += num
            break
        if ord(item) == 45:
            num = int(''.join(map(str, templist)))
            if signal == 45:
                ans -= num
            elif signal == 43:
                ans += num
            signal = 45
            templist.clear()
        elif ord(item) == 43:
            num = int(''.join(map(str, templist)))
            if signal == 45:
                ans -= num
            elif signal == 43:
                ans += num
            signal = 43
            templist.clear()
        else : templist.append(item)
    return int(ans)

코드 해석 : 

1. signal을 저장한다.

2. 숫자를 templist 에 저장한다.

3. 다음 부호를 만났을 때, 저장한 templist를 map으로 개행한다.

4. join으로 문자열로 합친다.

5. 이를 숫자로 만들어, 저장한 signal을 활용해 ans에 계산한다.

6. 첫번째 문자가 부호가 아닌 숫자가 올 때는 바로 templist에 저장하며, 이때 signal은 +로 저장한다. (시작을 +로 했다.)

7. 마지막 문자일 경우 3번의 과정을 진행한다.

 

def solution(s):

    result = eval(s)

    return result

한석님 코드

eval()이라는 함수는 문자열로 적힌 계산식을 바로 계산해준다.

 

def solution(s):
    index = []
    x = 0
    for i in range(len(s)):
        if s[i] == '+' or s[i] == '-':
            index.append(i)
        elif ('+' not in s) and ('-' not in s):
            return int(s)

    for j in range(len(index)):
        if index[j] == index[-1]:
            x += int(s[index[j]:]) -3+26-7
        else:
            x += int(s[index[j]:index[j+1]]) 0 ~ 1 / 2 ~ 4 / 5

    return x

재경님 코드

1. 부호의 인덱스를 리스트에 저장한다.

2. 부호의 인덱스 사이 값을 숫자로 만들어준다.

3. 부호와 숫자가 합쳐진 문자열을 int로 캐스팅해준다.   '-3' -> -3

4. 마지막에 부호가 없을 경우, 2번, 3번 과정을 바로 해준다.

 

🥕 6번 - area가 주어졌을 때, w와 h 차이 가장 적을 때의 w,h 구하기. 단 w가 더 작거나 같아야함

내 코드

import math
def solution(area):
    mylist = []
    for i in range(1,int((math.sqrt(area)))+1):
        if area % i == 0:
            mylist.append(i)
    w = mylist[-1]
    h = area // w
    return [w,h]

1. 약수를 int(math.sqrt(area)) 까지만 구해준 뒤 ( range 함수 인 것을 고려하여 +1을 해준다. )

2. 리스트를 만든 후, 리스트의 마지막 값에 약수의 작은 범위에 속하는 것 중 가장 큰 값이 오므로 이를 w로 해주고

3. h는 area에서 w로 나눠 바로 구해준다.

🥕 7번 - 이진법으로 바꿨을 때, 떨어진 1의 사이가 가장 클때의 거리값

문제 분석 : 10010001 일 경우 가장 큰 거리는 3이다.

def solution(n):
    s = bin(n)[2:]
    slist = s.split('1')
    w = 0
    for i in slist:
        if len(i) > w:
            w = len(i)
    return w+1

1. 1을 기점으로 split로 끊어 리스트를 만들어준다. ex) [00,000]

2. 요소의 길이를 재서 가장 긴 값을 반환해준다.

 

🥕 8번 - 확진자와 동선 겹치는 사람 구하기

내 코드

def solution(history, infected):
    cnt = history.count(infected)
    attendlist = []
    exitlist = []
    attend, exit = -1,-1
    for i in range(cnt):
        attend = history.index(infected,attend+1,len(history))
        attendlist.append(attend)
        exit = history.index(-infected,exit+1,len(history))
        exitlist.append(exit)

    anslist = []
    result = []
    for i in range(cnt):
        anslist.extend(history[attendlist[i]:exitlist[i]])
    for idx,item in enumerate(anslist):
        anslist[idx] = abs(item)
    for i in (set(anslist)-{infected} ):
        result.append(i)
    result = sorted(result)
    return result

1. 확진자의 attend와 exit의 인덱스를 담은 리스트를 각각 만들어주고

2. 1에서 구한 인덱스를 가지고 확진자 동선 안의 다른 사람들의 입장과 퇴장을 모두 extend로 합쳐준다.

3. 각 요소를 abs로 절대값을 구해준 뒤

4. 집합 기호로 중복을 제거하였다.

5. 집합의 요소를 리스트로 만든 후, 정렬하여 반환하였다.

 

🥕 10번 - 나무 판자 재활용 문제

def solution(l):
    maxArea=0
    for start, item in enumerate(l):
        w=0
        for i in l[start:]:
            if l[start]>i:
                break
            w += 1
        if maxArea < w*l[start]:
            maxArea = w*l[start]
    return maxArea

왼쪽을 기점으로 해서 가장 큰 area를 구해줬다.

다만 이는 오른쪽을 기점으로 했을 때는 고려하지 못한 코드여서

방향만 오른쪽으로 바꿔줘서 한번 더 구하고

가장 큰 area를 구해주면 될 것 같다.