4 minute read


title

sport

2021 kakao intern

1

py solution

keys = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
vals = ['0','1','2','3','4','5','6','7','8','9']
dic = {}

def solve(s):
    ans = []
    pos = 0
    slen = len(s)
    
    for i in range(10):
        dic[keys[i]] = vals[i]

    # print(dic)
    while pos < slen:
        l1 = s[pos]
        # print('l1', l1)
        if(is_int(l1)):
            ans.append(str(l1))
            pos+=1
            # print('ADD')
            continue

        l3 = s[pos:pos+3]
        l4 = s[pos:pos+4]
        l5 = s[pos:pos+5]
        
        if(l3 in dic):
            pos+=3
            ans.append(dic[l3])
            # print('t1')
        elif(l4 in dic):
            pos+=4
            ans.append(dic[l4])
            # print('t2')
        elif(l5 in dic):
            pos+=5
            ans.append(dic[l5])
            # # print('t3')
        

    # print(ans)
    return int(''.join(ans))

2

py solution

dr = [1,0,0,-1]
dc = [0,1,-1,0]

def solve(places):
    ans = []
    for t in places:
        # print('T', t)
        maps = create2DArray(5,5,-1)
        for rr,row in enumerate(t):
            for cc,c in enumerate(row):
                maps[rr][cc] = row[cc]
        # print('maps',maps)

        # 어떻게 해야 노가다 구현을 피할 수 있을까
        # 음...
        
        fail = False
        for sr in range(5):
            for sc in range(5):
                c = maps[sr][sc]
                if(c == 'X'):
                    continue
                
                cnts_man = 0
                
                for i in range(4):
                    nr,nc = sr+dr[i], sc+dc[i]
                    if((0<=nr<5) and (0<=nc<5)):
                        if(maps[nr][nc] == 'P'):
                            cnts_man+=1
                if(c == 'O' and cnts_man>=2):
                    fail = True
                    pass
                elif(c == 'P' and cnts_man >= 1):
                    fail = True
        if fail:
            ans.append(0)
        else:
            ans.append(1)
            
    return ans

3

py solution

def solve(n,k,cmd):
    # print(n,k,cmd)

    # U, D 이동
    # C 삭제, 다음 행 또는 마지막 행이면 이전 행 선택
    # Z 가장 최근 삭제 복구, 선택 행은 보존

    # 리턴: 각 행별 삭제 여부 OX 표시 문자열

    # 제한:
    # n ~ 100만
    # cmd ~ 20만

    # 다음 행, 이전 행에 대한 정보 및 현재 선택 행에 대한 정보가 필요

    # 효율적으로 이동하려면, C로 삭제를 할 때 위아래를 연결시켜야 하는데, 
    # 그러면 다시 복구할때 복잡해진다.

    # 또, 복구할 때 진짜 어려운 것은 커서를 어떻게 관리하느냐다.
    # 삭제시에는 커서를 직접 옮겨주는데,
    # 복구시에는 그대로 두면 되나??

    table = {}
    cursor = k+1
    
    for i in range(1, n+1):
        # prev, next, alive
        newr = [i-1 if i != 1 else -1, i+1 if i != n else -1, 1, i]
        table[i] = newr

    # print('table', table, 'cursor', cursor)
    
    def move(direction, amount):
        nonlocal cursor
        if(amount <= 0):
            return

        if(direction == 'U'):
            next_cursor = table[cursor][0]
        else:
            next_cursor = table[cursor][1]
        if(next_cursor != -1):
            cursor = next_cursor
        amount-=1
        move(direction, amount)
        
        pass

    def remove():
        nonlocal cursor
        cur = table[cursor]
        my_prev, my_next, val, num = cur
        nextc = cur[1]

        cur[2] = 0

        # link prev's next to my next
        if(my_prev != -1):
            # print('table[my_prev][1] = my_next', table[my_prev][1], my_next)
            table[my_prev][1] = my_next

        # link next's prev to my prev
        if(my_next != -1):
            table[my_next][0] = my_prev
        
        if(nextc != -1):
            cursor = nextc
        else:
            cursor = cur[0]
        
        return cur

    def recover(target):
        # nonlocal cursor

        # recover
        target[2] = 1
        cur = table[target[3]] = target
        # cur[2] = 1
        my_prev, my_next, val, num = cur

        # recover my prev's next to me
        if(my_prev != -1):
            table[my_prev][1] = target[3]
        
        # recover my next's prev to me
        if(my_next != -1):
            table[my_next][0] = target[3]
        
        pass
    
    stack = []
    for i,cmdstr in enumerate(cmd):
        cmds =  cmdstr.split(' ')
        # print(cmds)
        typ = cmds[0]
        
        if typ == 'C':
            target = remove()
            stack.append(target)
        elif typ == 'Z':
            target = stack.pop()
            # print('target',target)
            recover(target)
        else:
            move(cmds[0], int(cmds[1]))
        
        # print('table', table, 'cursor', cursor)
        # print(''.join([str('C' if x == cursor else ('O' if table[x][2] == 1 else 'X')) for x in table]))
    ans = ''.join([str('O' if table[x][2] == 1 else 'X') for x in table])
    return ans

4

방식은 이해했는데, cpp에서는 map<tuple<int, map<int, int>>, bool>이런 복잡한 구조를 가지는 맵(사전) 구조를 이용하여 푸는데, 파이썬에서는 dict에 dict를 키로 사용하려 하면 nonhashable 관련 에러가 나서 안 된다. 게다가, 트릭을 사용한 hashabledict를 만들어서 시도해봐도 이중 인덱싱이 defaultdict와 겹쳐 제대로 체크되지가 않는다..

py wrong solution

class hashabledict(dict):
    def __hash__(self):
        return hash(tuple(sorted(self.items())))
        
def solve(n,start,end,roads,traps):
    from collections import defaultdict
    import heapq
    import json
    gf = defaultdict(list)
    gr = defaultdict(list)
    
    toggle_state = hashabledict()
    traps_set = set()
    costs = [defaultdict(lambda: 999999999999) for x in range(n+1)]

    for i,v in enumerate(roads):
        p,q,s = v
        gf[p].append((q,s))
        gr[q].append((p,s))
    
    for v in traps:
        toggle_state[v] = 1
        traps_set.add(v)
        
    def get_state_val(state, node):
        nonlocal traps_set
        # print('state', state)
        if(node in traps_set):
            return state[node]
        else:
            return 1

    # print(gf)
    # print(gr)
    # print(toggle_state)
    
    # cur_pos, cur_cost, toggle_state
    init_state = toggle_state
    init = (0, start, init_state)
    q = []
    heapq.heappush(q, init)
    costs[start][init_state] = 0
    # q.append(init)

    while len(q)>0:
        # pos, cost, state_str = q.pop()
        cost, pos, state = heapq.heappop(q)
        if(pos == end):
            # print('END', end, cost)
            return cost 
        # calc avail edges from current pos
        
        forwards = gf[pos] # 현재 노드에서 나가는 집합.
        backwards = gr[pos] # 현재 노드로 들어오는 집합
        costs[pos][state] = cost
        print('costs', costs)
        
        # 각 on/off 상태의 state 맵으로부터,
        # 현재 노드로부터 갈 수 있는 edge들을 계산.
        # 일단 그러려면, 각 엣지에 대해, 연결된 노드들을 알아야 하고,
        # 각 노드들의 state는 알고 있으므로 적용해주면 된다.
        # 문제는, 각 엣지에 대해 연결된 노드들을 어떻게 표현할 것인가이다.
        
        # 그리고, 모든 엣지에 대해 하면 비효율적이므로, 현재 노드에 연결되고, 들어오는 간선에 
        # 대해서만 검사하는게 효율적이다.
        # forwards[i] : 현재 노드 state * 연결 노드 state > 0이면 가능
        # backwards[i] : 현재 노드 state * 연결 노드 state < 0 이면 가능?
        
        next_edges = []
        cur_state_v = get_state_val(state, pos)
        
        for fwd in forwards:
            nn, ww = fwd
            if(cur_state_v * get_state_val(state, nn) > 0):
                next_edges.append((nn, ww))
        for bwd in backwards:
            nn, ww = bwd
            if(cur_state_v * get_state_val(state, nn) < 0):
                next_edges.append((nn, ww))
        for next_edge in next_edges:
            new_state = copy.deepcopy(state)
            nn, ww = next_edge
            print('test nn', nn, 'ww',ww, 'state', state)
            if(nn in traps_set):
                new_state[nn] *= -1
                if(cost+ww < costs[nn][new_state]):
                    q.append((cost+ww, nn, new_state))
            else:
                if(cost+ww < costs[nn][new_state]):
                    q.append((cost+ww, nn, new_state))
        pass

blog

테스트 데이터를 만드는 쪽에서도 이렇게 어려운 작업이 필요하단 것을 알았다. 신기하다. http://www.secmem.org/blog/2019/01/09/wrong-dijkstra/


Comments