2021년 07월 21일 수요일 IT뉴스

1. 네이버-CJ, 풀필먼트 센터 확충…’당일배송·새벽배송’ 뛰어든다(종합)

네이버-CJ, 풀필먼트 센터 확충…’당일배송·새벽배송’ 뛰어든다(종합)

네이버는 CJ대한통운과 함께 네이버 스마트스토어 판매자를 중심으로 전국 빠른 배송 서비스를 구축한다고 21일 밝혔고, 기존 네이버 스마트스토어를 중심으로 운영해온 곤지암·용인·군포 풀필먼트 센터에 이어 추가로 20만평 규모의 풀필먼트 센터를 설립한다.

네이버는 지난 12일 풀필먼트 데이터 플랫폼 ‘NFA’를 열었고, 이어 네이버는 지난 20일 특수 물류 전문 업체 발렉스와 손잡고 프리미엄 배송 실험을 시작했으며, ‘희망일 배송’까지 네이버의 NFA를 통해 다양한 배송 서비스 지원을 확대할 계획이다.

  • 풀필먼트는 물류 전문업체가 판매자 대신 주문의 포장과 배송까지 담당하는 서비스를 말한다.
  • NFA는 네이버의 인공지능(AI)을 기술력을 이용해 물류 데이터 분석, 사업자별 물류 수요예측 등의 기능을 제공하는 서비스다.
  • 프리미엄 서비스는 고가의 전자제품을 금고와 폐쇄회로(CC)TV, GPS 등이 설치된 보안 차량으로 상품을 안전하게 배송하는 서비스다.

2. 암 진단 AI ‘왓슨’ 빈자리 누가 채우나…치료까지 넘보는 한국 AI스타트업

암 진단 AI ‘왓슨’ 빈자리 누가 채우나…치료까지 넘보는 한국 AI스타트업

유방암·폐암 진단보조 AI '루닛 인사이트'(왼쪽)와 항암제 반응 예측 AI '루닛 스코프'. [사진 루닛]

지난 2011년 IBM이 선보였던 인공지능(AI) 왓슨은 암 진단 정확도를 높일 주역으로 주목받았지만, 10년이 지난 현재, 기대만 못 한 정확도에 위기를 겪고 있으며, 의료AI 스타트업들이 암 치료에 도전하면서 왓슨이 설 자리는 더 좁아진 모양새다.

대표적인 곳이 국내 의료AI 스타트업인 루닛으로, 지난 19일 루닛은 미국의 바이오 헬스케어기업인 ‘가던트헬스(Guardant Health)’로부터 약 300억원 규모의 시리즈C 후속 투자를 받았다. 가던트헬스는 암 정밀 분석법인 액체생검 분야에서 선도적인 위치에 있으며, 미국 혈액종양내과 전문의 중 80%가 이곳 제품을 쓰는 것으로 알려져 있다.


3. 마이크로소프트, 윈도365로 기업 업무환경 바꾼다

마이크로소프트, 윈도365로 기업 업무환경 바꾼다

마이크로소프트가 공개한 윈도365 개념도.

윈도365는 윈도10 환경을 클라우드서비스 애저에 구축하고, 웹브라우저를 통해 접속하는 가상데스크톱인프라(VDI) 서비스로, PC가 아닌 맥, 아이패드, 안드로이드 스마트폰 등에서도 웹브라우저를 통해 윈도 환경에 접근해 업무를 수행할 수 있고 하드웨어의 종류나 성능, 장소 제약 없이 윈도를 사용할 수 있어 원격 업무환경 지원에 용이하다.

대기업에서 필요한 재택근무 시스템은 윈도와 문서도구 외에도, 전사적자원관리(ERP), 공급망관리(SCM), 고객관계관리(SCM) 등 대규모 IT서비스와 연계가 필요하여 파트너사에 의뢰해 직접 VDI를 구축하거나, 윈도365에 필요한 기능을 더하는 추가 작업이 필수적이다.

나무기술의 권세창 과장은 “대기업과 금융권에서 VDI를 사용하기 위해선 윈도10 외에도 수백 종의 협업 도구를 포함하고 있어 윈도365 단독으로 제공하긴 어려울 것”이라며 “IT서비스 기업에게 윈도365는 대기업 VDI 구성을 위한 하나의 옵션으로 보는 것이 더 적합할 것”이라고 설명했다.


4. [유튜피아] 진격의 ‘틱톡’에 따라잡힌 유튜브…’틱톡 따라하기’ 맞불

[유튜피아] 진격의 ‘틱톡’에 따라잡힌 유튜브…’틱톡 따라하기’ 맞불

동영상 플랫폼 절대 강자 ‘유튜브’가 흔들리고 있다. 이미 일부 국가의 경우 ‘틱톡’의 이용시간이 유튜브를 앞지른 것으로 나타났다.

미국·영국·한국의 틱톡, 유튜브 월평균 소비 시간 (앱애니 블로그 캡처) © 뉴스1

유튜브가 ‘숏폼’ 콘텐츠를 전면에 내세우며 틱톡 따라잡기에 나섰다면, 틱톡은 동영상의 제한 길이를 늘려 ‘유튜브’ 따라잡기에 나섰다. 틱톡은 지난 1일 영상의 길이 제한을 기존 1분에서 3분으로 대폭 늘린다는 계획을 내놨다. 15초 길이의 짧은 영상에서 60초까지 영상 길이를 늘렸던 틱톡이 3분짜리 동영상으로 유튜브를 정조준한 것이다.


5. “왜 불편하게 바꾸나” T멤버십 놓고 와글와글

“왜 불편하게 바꾸나” T멤버십 놓고 와글와글

현재 SK텔레콤 T멤버십 프로그램은 제휴 브랜드인 파리바게뜨·CU 등에서 1000원 상당의 물품을 구매하고 등급에 따라 50~100원 할인된 금액만을 결제하는 방식이지만, 앞으로는 할인 금액만큼의 포인트를 우선 적립하고, 원하는 제휴 브랜드 매장만을 골라서 적립한 금액을 한 번에 사용할 수 있다.

김대종 세종대 경영학부 교수는 “포인트 적립으로 멤버십을 바꾸는 것은 포인트가 몇 년 후 소멸된다는 점, 구매 당시 바로 할인을 받을 수 없다는 점에서 당연히 소비자에게 불리한 방식”이라고 말했다.

일각에서는 일정 수준 이상 포인트를 모아야 사용할 수 있는 ‘최소 사용 금액’ 도입을 우려하는 목소리도 나온다. 예컨대 제휴 브랜드에서 적립된 포인트를 사용하려고 해도 ‘포인트 1000원 이상 사용 가능’ 같은 기준이 정해져 있어 이 금액을 넘는 적립액을 쌓기 위한 소비를 지속적으로 해야 한다는 것이다.

[백준] 11116번 교통량

[백준] 11116번 교통량

출처: [백준] 11116번 교통량


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 256 MB 55 35 31 62.000%

문제

승민이는 마포대교의 교통량이 얼마인지를 측정하고있다. 승민이는 도로 맞은 편을 잇는 두개의 끈을 일정 간격 사이로 매달아 놓았다. 그리고 자동차가 끈위로 지나갈때 끈 끝에 있는 작은 박스에는 그 때 의 시간이 기록된다.

예를 들어, 자동차가 왼쪽에서 올 때 네 번의 기록을 얻게 된다.

  • 왼쪽 줄 위로 앞 바퀴가 지나 간 시간 t
  • 왼쪽 줄 위로 뒷 바퀴가 지나 간 시간 t + 500
  • 오른쪽 줄 위로 앞 바퀴가 지나 간 시간 t + 1000
  • 오른쪽 줄 위로 뒷 바퀴가 지나 간 시간 t + 1500

자동차가 오른쪽에서 올 때도 같은 규칙으로 오른쪽과 왼쪽을 바꾸어 측정하면 된다. 주어진 두개의 시간 기록으로 왼쪽에서 얼마나 많은 차가 왔는지 알아내면 된다. 한 끈 위에는 많아야 한 대의 차량이 지나가고 있다.


입력

첫 번째 줄에 n (1 ≤ n ≤ 100) 까지의 테스트 케이스의 개수를 입력 한다. 각각의 테스트 케이스에는 박스에서 측정 된 시간 기록의 개수 m (m ≤ 200)을 입력한다. 다음 줄에는 왼쪽 박스에서 측정된 109 보다 작은 시간 기록 m개를 입력한다. 그 다음 줄에는 오른쪽 박스에서 측정된 109 보다 작은 시간 기록 m개를 입력한다.


출력

각각의 테스트케이스에 대해 왼쪽에서 오는 차의 숫자를 출력한다.


예제 입력 1

1
2
3
4
5
6
7
2
4
17 517 1432 1932
432 932 1017 1517
6
235 451 735 951 2351 2851
1235 1351 1451 1735 1851 1951

예제 출력 1

1
2
1
2

힌트

예제의 첫 번째 테스트 케이스인 Case #1은 문제에서 예로들어서 설명한 세 개의 물품에 대한 정상가격과 할인가격 6개입니다. 또한 예제의 Case #2에서는 여러 품목이 동일한 가격을 가질 수 있고, 어떤 품목의 할인가격이 다른 품목 정상가격과 같을 수도 있습니다.


출처


알고리즘 분류


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sys
from collections import deque

input = sys.stdin.readline

N = int(input())

for _ in range(N):
M = int(input())
left_box = deque(map(int, input().split()))
right_box = deque(map(int, input().split()))

car_count = 0
count = 0
while left_box:
temp = left_box.popleft()
if temp + 1000 in right_box:
count += 1
if count == 2:
count = 0
car_count += 1

print(car_count)

[백준] 12034번 김인천씨의 식료품가게 (Large)

[백준] 12034번 김인천씨의 식료품가게 (Large)

출처: [백준] 12034번 김인천씨의 식료품가게 (Large)


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
5 초 512 MB 253 128 118 50.862%

문제

전설적인 인천 식료품가게의 주인인 김인천 씨는 대대적인 할인행사를 계획하고 있습니다. 계산을 단순하게하기 위해 그는 25% 할인된 가격으로 상점의 모든 품목을 판매하기로 결정했습니다. 즉, 각 품목의 판매 가격은 정상 가격의 정확히 75 %입니다. 우연하게도 인천 식료품가게에서 판매하는 모든 물건의 정상가는 4의 배수인 정수이고, 할인된 가격 역시 편리하게도 모두 정수입니다.

김인천씨는 이 할인행사를 준비하기위해서 먼저 모든 판매물품의 할인된 판매가격을 프린터로 출력을 실행했고, 또한 할인행사 종료후 다시 쓸 모든 품목에 정상가격표 역시 출력을 실행하였습니다.

손님이 찾아와 잠깐 자리를 비웠던 김인천씨가 다시 가격표의 출력을 확인하기 위해서 프린터로 돌아와보니, 공교롭게 프린터는 모든 물품의 할인가격과 정상가격을 따로 구분하지 않고 오름차순으로 정렬한 뒤 순서대로 출력하여 하나의 출력물 더미를 만들었습니다. 각 품목의 할인가격표와 정상가격표 모두가 출력물 더미의 어딘가에 있습니다. 그러나 두 유형(할인가격, 정상가격)의 가격표는 비슷하게 보이고, 모든 품목의 가격을 기억하지 못하기 때문에 김인천씨는 어느 가격표가 할인가격표인지 확신할 수 없습니다. 이 상황에서 김인천씨는 무엇이 할인가격표인지 구분해낼 수 있을까요?

예를 들어, 정상가격이 20, 80, 100 인 경우 할인가격은 15, 60, 75이며 프린터의 인쇄출력더미는 오름차순으로 정렬된 15, 20, 60, 75, 80, 100 가격표들로 구성됩니다.


입력

입력의 첫 번째 라인(줄)은 테스트 사례의 케이스의 수 T를 나타냅니다. 이후의 라인은 T개의 테스트 케이스가 이어집니다. 각 테스트 케이스는 두 줄로 구성됩니다. 첫 번째 줄에는 INU 식료품가게에 존재하는 상품수인 단일 정수 N이 포함됩니다. 두 번째 줄에는 프린터에서 가격의 오름차순으로 인쇄한 2N개의 정수 P1, P2, …, P2N이 주어집니다.

입력값의 제한은 아래와 같습니다

  • 1 ≤ T ≤ 100.
  • 모든 i에 대해서 1 ≤ Pi ≤ 109.
  • 모든 i에 대해서 Pi ≤ Pi+1. (가격은 오름차순으로 존재)
  • 정답은 단 하나만 존재하는것이 보장되어 있음.
  • 1 ≤ N ≤ 100

출력

개별 테스트 케이스에 대해서 출력라인은 “Case #x: y” 형식(큰 따옴표는 제외)으로 출력하며, x는 1부터 시작하는 테스트 케이스의 번호 (인덱스)이며, y는 할인가격에 해당하는 오름차순으로 정렬된 N개의 정수들이다.


예제 입력 1

1
2
3
4
5
2
3
15 20 60 75 80 100
4
9 9 12 12 12 15 16 20

예제 출력 1

1
2
Case #1: 15 60 75
Case #2: 9 9 12 15

힌트

예제의 첫 번째 테스트 케이스인 Case #1은 문제에서 예로들어서 설명한 세 개의 물품에 대한 정상가격과 할인가격 6개입니다. 또한 예제의 Case #2에서는 여러 품목이 동일한 가격을 가질 수 있고, 어떤 품목의 할인가격이 다른 품목 정상가격과 같을 수도 있습니다.


출처


알고리즘 분류


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import sys

input = sys.stdin.readline

T = int(input())

for t in range(T):
N = int(input())
price_list = sorted(map(int, input().split()), reverse=True)
dc_list = []

while price_list:
price = price_list.pop()

if price * 100 // 75 in price_list:
dc_list.append(price)
price_list.remove(price * 100 // 75)

print("Case #{0}: ".format(t + 1), end="")
print(*dc_list)

[백준] 15828번 Router

[백준] 15828번 Router

출처: [백준] 17952번 과제는 끝나지 않아!


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 512 MB 746 440 375 61.275%

문제

인터넷을 사용하기 위해서는 컴퓨터에 인터넷 회선을 연결하거나 Wi-Fi를 연결해야 한다. 이렇게 연결된 네트워크를 통해 컴퓨터에는 통신이 가능하다. 마음에 드는 노래나 동영상이 있는 곳에 파일을 전송해달라는 요청을 보내고 파일을 받는 식으로 말이다.

우리가 보낸 요청은 어떻게 목적지까지 도달하는 것일까? 컴퓨터에서는 패킷이라고 하는 형태로 정보를 주고 받는다. 네트워크의 유저들은 1:1로 연결되어 있지 않으므로, 일반적으로 패킷은 라우터라는 장비를 여러 번 거친다. 그러면 라우터에서는 패킷을 다른 라우터로 보내거나, 만약 목적지와 직접적으로 연결되어 있다면 그곳으로 보낼 수도 있다. 즉, 택배 회사의 물류 센터와 비슷한 역할을 한다고 보면 된다.

img

그림1. 네트워크에 존재하는 라우터들의 구성 예시

라우터 내부를 들여다보면 처리해야 할 패킷을 임시적으로 보관하기 위한 버퍼가 존재한다. 이 버퍼에는 라우터에 입력으로 들어온 패킷들이 순서대로 위치하고, 라우터에서는 먼저 온 패킷부터 하나씩 처리한 후 버퍼에서 제거한다. 만약 라우터가 패킷을 처리하는 속도보다 패킷이 들어오는 속도가 더 빠를경우 버퍼가 꽉 차거나 넘쳐버릴 것이다. 그렇게 되면 버퍼에 공간이 생길 때까지 입력받는 패킷은 모두 버려진다.

통신의 원리를 배웠으니까 간단하게 라우터의 작동 원리를 구현해보자. 물론 하나의 라우터만 존재한다고 가정하며, 우리가 다룰 부분은 라우터의 입출력이 주어졌을 때 버퍼의 상태가 어떻게 변하는가이다. 그러니까 라우터가 패킷을 구체적으로 어떤 방식으로 처리하고, 어디로 보내고 이런 것들은 생각하지 말자.


입력

첫 줄에는 라우터 내부에 존재하는 버퍼의 크기를 나타내는 자연수 N이 주어진다.

둘째 줄부터 한 줄에 하나씩 라우터가 처리해야 할 정보가 주어진다. 모든 정보는 발생한 시간순으로 주어졌다고 가정한다. 양의 정수는 해당하는 번호의 패킷이 입력으로 들어왔다는 것을 의미하고, 0은 라우터가 패킷 하나를 처리했다는 것을 의미한다. 이때, 버퍼가 비어있을때는 0이 입력으로 들어오지 않는다. -1은 입력의 끝을 나타낸다.


출력

라우터에 남아있는 패킷을 앞에서부터 순서대로 공백으로 구분해서 출력하면 된다. 만약 비어있을 경우 empty라고 출력한다.


Small (50점)

  • 1 ≤ N ≤ 100,000
  • 라우터가 처리해야 할 정보의 수는 N보다 작거나 같다.

Large(50점)

  • 1 ≤ N ≤ 100,000
  • 1 ≤ N ≤ 100,000

예제 입력 1

1
2
3
4
5
6
7
8
9
10
11
12
5
1
2
0
3
4
0
5
6
0
0
-1

예제 출력 1

1
5 6

예제 입력 2

1
2
3
4
5
6
7
8
9
1
1
2
3
4
5
6
7
-1

예제 출력 2

1
1

예제 입력 3

1
2
3
4
5
6
7
8
9
10
11
12
13
1
1
2
0
3
4
0
5
6
0
7
0
-1

예제 출력 3

1
empty

출처


알고리즘 분류


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import sys
from collections import deque

input = sys.stdin.readline

N = int(input())
buffer = deque()
full = 0
while True:
packet = int(input())

if packet == -1:
break
elif packet == 0:
buffer.popleft()
full -= 1
else:
if full >= N:
continue
else:
buffer.append(packet)
full += 1

if buffer:
print(*buffer)
else:
print("empty")

[백준] 17225번 세훈이의 선물가게

[백준] 17225번 세훈이의 선물가게

출처: [백준] 17225번 세훈이의 선물가게


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 512 MB 1120 261 197 29.315%

문제

세훈이는 선물가게를 운영한다. 세훈이의 선물가게는 특이하게도 손님이 어떤 선물을 구매할지 선택할 수가 없다. 대신 세훈이의 취향으로 랜덤하게 준비된 선물 중 몇 개를 구매할 것인지, 파란색과 빨간색 중 어떤 색으로 포장 받을 것인지만 결정해 주문할 수 있다.

상민이와 지수는 세훈이의 가게에서 선물 포장을 맡은 아르바이트생이다. 손님들은 파란색 포장지를 원하면 상민이에게, 빨간색 포장지를 원하면 지수에게 주문을 한다. 두 사람은 각자 주문을 받으면 그때부터 포장을 시작하는데, 현재 남아있는 선물 중 가장 앞에 있는 선물을 가져와 포장하고 주문을 받은 개수만큼 이를 반복하는 형태다. 이때 선물 하나를 포장하는 데 상민이는 A초, 지수는 B초가 걸린다. 두 사람 모두 받거나 밀린 주문이 없는데 미리 선물을 가져오거나 포장하는 일은 없으며, 두 사람이 동시에 선물을 가져올 때는 알바짬이 조금 더 있는 상민이가 먼저 가져오고, 지수가 그 뒤의 선물을 가져온다.

세훈이는 어제 구매한 선물이 망가져 있다는 항의 전화를 받았다. 자신이 준비한 선물에는 문제가 없었기에 손님에게 포장지의 색을 물었지만, 손님은 자신이 받은 선물이 무엇인지만 말하며 화를 낼 뿐이었다. 어쩔 수 없이 세훈이는 어제 가게를 방문한 손님들의 주문 내역을 보고 그 선물을 누가 포장했는지 파악하려 한다.

방문한 손님의 수와 각 손님이 주문한 시각, 선택한 포장지, 포장 받을 선물의 개수가 주어졌을 때 상민이와 지수가 각자 어떤 선물들을 포장했는지 알아내는 프로그램을 작성해보자.


입력

첫 줄에 상민이가 선물 하나를 포장하는 데 걸리는 시간 A, 지수가 선물 하나를 포장하는 데 걸리는 시간 B, 어제 세훈이 가게의 손님 수 N(1 ≤ N ≤ 1,000)이 주어진다.

이후 N개의 줄에 걸쳐 1번부터 N번 손님의 주문 시각 ti(1 ≤ ti ≤ 86,400), 선택한 포장지의 색깔 ci(ci = “B”|”R”), 주문한 선물의 개수 mi(1 ≤ mi ≤ 100)가 주어진다.

ti는 가게가 오픈한 지 ti초 후에 손님이 주문했음을 뜻하며 ci는 포장지의 색깔을 의미하는 알파벳으로 “B”는 파란색을, “R”은 빨간색을 의미한다. 주어지는 입력은 시간의 흐름에 맞게 ti의 오름차순으로 주어지며, 서로 같은 시간에 주문한 손님은 없다.


출력

첫 번째 줄에 상민이가 포장한 선물의 개수를 출력한다. 이후 두 번째 줄에 상민이가 포장한 선물들의 번호를 오름차순으로 공백으로 구분하여 출력한다.

세 번째 줄에 지수가 포장한 선물의 개수를 출력한다. 이후 네 번째 줄에 지수가 포장한 선물들의 번호를 오름차순으로 공백으로 구분하여 출력한다.


서브태스크 1 (100점)

  • A = B = 0

A, B가 0이라는 것은 해당 아르바이트생의 포장 속도가 너무 빨라서, 주문과 동시에 해당 주문의 모든 선물 포장이 끝난다는 의미이다.

서브태스크 2 (40점)

  • 0 ≤ A, B ≤ 300

예제 입력 1

1
2
3
4
0 0 3
1 B 3
4 R 2
7 R 2

예제 출력 1

1
2
3
4
3
1 2 3
4
4 5 6 7

<그림1> 예제1 시간에 따른 상민이와 지수의 행동

예제 입력 2

1
2
3
4
5
2 3 4
1 B 3
4 R 2
6 B 2
12 R 1

예제 출력 2

1
2
3
4
5
1 2 4 5 7
3
3 6 8

<그림2> 예제2 시간에 따른 상민이와 지수의 행동


출처


알고리즘 분류


소스코드 (Heap 이용)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import sys
import heapq

input = sys.stdin.readline

s_time, j_time, customer_count = map(int, input().split()) # 상민 포장시간, 지수 포장시간, 손님수
pacakage_list = [] # 포장시작 시간 리스트
s_end, j_end = 0, 0 # 상민, 지수 포장 끝난 시간

for _ in range(customer_count):
start_time, color, present_count = input().rstrip().split() # 주문시각, 색깔, 개수
start_time = int(start_time)

if color == 'B': # 상민

# 상민 포장 주문시각이 포장끝난 시각보다 먼저일 경우
# 주문시각(포장시작시각)을 포장끝난 시점으로 변경해준다.
start_time = max(start_time, s_end)

for i in range(int(present_count)): # 주문 개수만큼 반복
heapq.heappush(pacakage_list, [start_time, 'B']) # 상민 포장시작 시간 리스트에 저장
start_time += s_time # 기존 포장시작시간에 포장에 걸리는 시간 더하기
s_end = start_time # 포장끝난 시간은 포장시작시간+포장에 걸리는 시간

elif color == 'R': # 지수
start_time = max(start_time, j_end)

for i in range(int(present_count)):
heapq.heappush(pacakage_list, [start_time, 'R'])
start_time += j_time
j_end = start_time

s_present, j_present = [], [] # 상민, 지수가 포장한 선물리스트

for i in range(1, len(pacakage_list) + 1):
present = heapq.heappop(pacakage_list)
if present[1] == 'B':
s_present.append(i)
else:
j_present.append(i)

print(len(s_present))
print(*s_present)
print(len(j_present))
print(*j_present)

소스코드 (Queue 이용)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import sys
from collections import deque

input = sys.stdin.readline

s_time, j_time, customer_count = map(int, input().split()) # 상민 포장시간, 지수 포장시간, 손님수
sangmin = deque() # 상민 포장시작 시간 리스트
jisu = deque() # 지수 포장시작 시간 시간 리스트
s_end, j_end = 0, 0 # 상민, 지수 포장 끝난 시간

for _ in range(customer_count):
start_time, color, present_count = input().rstrip().split() # 주문시각, 색깔, 개수
start_time = int(start_time)

if color == 'B': # 상민
start_time = max(start_time, s_end)
# if start_time < s_end: # 상민 포장 주문시각이 포장끝난 시각보다 먼저일 경우
# start_time = s_end # 주문시각(포장시작시각)을 포장끝난 시점으로 변경해준다.

for i in range(int(present_count)): # 주문 개수만큼 반복
sangmin.append([start_time, 'B']) # 상민 포장시작 시간 리스트에 저장
start_time += s_time # 기존 포장시작시간에 포장에 걸리는 시간 더하기
s_end = start_time # 포장끝난 시간은 포장시작시간+포장에 걸리는 시간

elif color == 'R': # 지수
start_time = max(start_time, j_end)
# if start_time < j_end:
# start_time = j_end

for i in range(int(present_count)):
jisu.append([start_time, 'R'])
start_time += j_time
j_end = start_time

total_list = sangmin + jisu
total_list = sorted(total_list, key=lambda x: [x[0], x[1]])

s_present, j_present = [], [] # 상민, 지수가 포장한 선물리스트

for idx, present in enumerate(total_list):
if present[1] == 'B':
s_present.append(idx + 1)
else:
j_present.append(idx + 1)

print(len(s_present))
print(*s_present)
print(len(j_present))
print(*j_present)

[백준] 14713번 앵무새

[백준] 14713번 앵무새

출처: [백준] 14713번 앵무새


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 512 MB 807 173 141 26.454%

문제

자가용 비행기를 타고 세계 일주를 하던 pps789와 cseteram은 어느 날 엔진 고장으로 인해 이름 모를 섬에 불시착하게 된다. 그들은 이 섬을 탐험하는 도중 아주 신기한 사실을 알게 되었는데, 바로 이 섬에 사는 앵무새들은 놀라울 정도로 인간의 말을 흉내 내는 데 뛰어나다는 것이다. 그들은 서로 떨어져 섬을 탐험하기로 하였으며, 필요하다면 앵무새를 이용해 서로에게 연락하기로 약속하였다.

1개월 후, pps789는 섬의 비밀을 밝힐 결정적인 증거를 찾게 된다. 그는 이 세기의 대발견을 cseteram에게 공유하고자 하였으나, 그의 발견은 방대하여 앵무새 한 마리가 기억하기에는 너무 많은 양이었다. 그렇기 에 pps789는 앵무새 한 마리 대신 앵무새 N마리를 이용하여 자신의 발견을 기록하였으며, 이 앵무새들을 cseteram을 향해 날렸다.

한편 섬의 반대편에서 탐험을 계속하던 cseteram은 앵무새 N마리가 자신에게 날아와 각자 할 말을 하는 것을 보고 당황하였다. pps789가 긴 글을 전달하고 싶었던 것은 알아차렸지만, 각각의 앵무새들이 말하는 것을 차례대로 기록하다 보니 원문이 무엇인지 알 수 없을 정도로 단어의 순서가 엉켜버린 것이다. 대신 그는 관찰을 통해 몇 가지 규칙을 발견할 수 있었다.

  1. 한 앵무새는 한 문장을 기억하고 있다. 문장은 여러 단어로 이루어져 있는데, 앵무새는 이 단어들을 순서대로 말한다.
  2. 한 앵무새가 단어를 말하고 그다음 단어를 말하기 전에는 약간의 간격이 있는데, 이때 다른 앵무새가 말을 가로채고 자신의 문장을 말할 수 있다.
  3. 한 앵무새가 단어를 말하는 도중에는, 다른 앵무새가 말을 가로채지 않는다.
  4. 어떤 단어도 앵무새가 말하는 모든 문장을 통틀어 2번 이상 등장하지 않는다.

앵무새는 자신이 기억하고 있는 문장을 끝까지 말한 다음 pps789에게 돌아가며, cseteram은 모든 앵무새가 돌아갈 때 까지 단어를 받아적는다. pps789가 각각의 앵무새들에게 전달한 문장 Si와, cseteram이 받아 적은 문장 L이 주어진다. 이때 문장 L이 위 규칙들을 이용하여 나올 수 있는 문장인지 판별하시오.


입력

첫 번째 줄에 앵무새의 수 N (1 ≤ N ≤ 100) 이 주어진다.

두 번째 줄부터 N개의 줄에 걸쳐 각 앵무새가 말한 문장 Si (1 ≤ i ≤ N) 가 주어지는데, 각 문장을 이루는 단어는 스페이스 한 칸을 구분으로 하여 주어진다. 문장 Si를 이루는 단어의 수는 1개 이상 100개 이하이며, 각 단어는 1개 이상 32개 이하의 영문 소문자로 구성되어있다.

N + 2 번째 줄에는 cseteram이 받아 적은 문장 L이 주어진다. 문장 L을 이루는 단어의 수는 1개 이상 10000개 이하이며, 각 단어는 1개 이상 32개 이하의 영문 소문자로 구성된다.


출력

문장 L이 가능한 문장이라면 Possible을, 불가능한 문장이라면 Impossible을 출력한다.


예제 입력 1

1
2
3
4
5
3
i want to see you
next week
good luck
i want next good luck week to see you

예제 출력 1

1
Possible

예제 입력 2

1
2
3
4
2
i found
an interesting cave
i found an cave interesting

예제 출력 2

1
Impossible

예제 입력 3

1
2
3
4
2
please
be careful
pen pineapple apple pen

예제 출력 3

1
Impossible

출처


알고리즘 분류


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import sys
from collections import deque

input = sys.stdin.readline

N = int(input())
parrot = [deque(input().rstrip().split()) for _ in range(N)]

L = input().rstrip().split()
Removed = []
for word in L:
for i in range(N):
if parrot[i] and word == parrot[i][0]:
parrot[i].popleft()
Removed.append(word)
break

for i in range(N):
if parrot[i]:
print("Impossible")
exit()
if L != Removed:
print("Impossible")
else:
print("Possible")

[백준] 2161번 카드1

[백준] 2161번 카드1

출처: [백준] 2161번 카드1


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
2 초 128 MB 5741 3921 3505 70.651%

문제

N장의 카드가 있다. 각각의 카드는 차례로 1부터 N까지의 번호가 붙어 있으며, 1번 카드가 제일 위에, N번 카드가 제일 아래인 상태로 순서대로 카드가 놓여 있다.

이제 다음과 같은 동작을 카드가 한 장 남을 때까지 반복하게 된다. 우선, 제일 위에 있는 카드를 바닥에 버린다. 그 다음, 제일 위에 있는 카드를 제일 아래에 있는 카드 밑으로 옮긴다.

예를 들어 N=4인 경우를 생각해 보자. 카드는 제일 위에서부터 1234 의 순서로 놓여있다. 1을 버리면 234가 남는다. 여기서 2를 제일 아래로 옮기면 342가 된다. 3을 버리면 42가 되고, 4를 밑으로 옮기면 24가 된다. 마지막으로 2를 버리고 나면, 버린 카드들은 순서대로 1 3 2가 되고, 남는 카드는 4가 된다.

N이 주어졌을 때, 버린 카드들을 순서대로 출력하고, 마지막에 남게 되는 카드를 출력하는 프로그램을 작성하시오.


입력

첫째 줄에 정수 N(1 ≤ N ≤ 1,000)이 주어진다.


출력

첫째 줄에 버리는 카드들을 순서대로 출력한다. 제일 마지막에는 남게 되는 카드의 번호를 출력한다.


예제 입력 1

1
7

예제 출력 1

1
1 3 5 7 4 2 6

출처

-


알고리즘 분류


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import sys
from collections import deque

input = sys.stdin.readline

N = int(input())

card_deque = deque([i for i in range(1, N + 1)])
removed_card = []

while len(card_deque) > 0:
removed_card.append(card_deque.popleft())
card_deque.rotate(-1)

print(*removed_card)

2021년 07월 19일 월요일 IT뉴스

1. 턱밑까지 추격한 샤오미… 폴더블폰이 삼성 구할까

턱밑까지 추격한 샤오미… 폴더블폰이 삼성 구할까

중국 샤오미가 올 2분기 전 세계 스마트폰 시장 2위에 오르며 삼성전자의 턱밑까지 치고 올라온 가운데, 애플이 9월 출시할 아이폰 차기작이 아이폰 역사상 최고 히트작이 될 것이라는 전망이 나오고 있어서 삼성전자가 중저가 시장에서는 샤오미에 밀리고, 수익성에서는 애플과 격차가 더 커지는 샌드위치 신세가 될 가능성이 높다는 것이다.

삼성전자는 특히 갤럭시Z폴드3와 갤럭시Z플립3의 가격을 각각 전작보다 40만원가량 낮춘 199만원과 128만원으로 책정하는 방안도 고민 중으로 폴더블폰 가격을 아이폰이나 갤럭시S 시리즈 수준까지 낮춰 새로운 수요를 개척하겠다는 것이며 하반기 전략 스마트폰인 갤럭시노트를 올해 출시하지 않는 승부수까지 던지면서 사실상 ‘폴더블 올인’ 전략을 구사하는 것이다.


2. 크래프톤, 인도 웹소설 플랫폼 ‘프라틸리피’에 515억 원 투자… 올해 인도 IT기업에 802억 투자 집행

크래프톤, 인도 웹소설 플랫폼 ‘프라틸리피’에 515억 원 투자… 올해 인도 IT기업에 802억 투자 집행

크래프톤이 인도 최대 웹소설 플랫폼 ‘프라틸리피(Pratilipi)’에 총 4,500만 달러(한화 약 515억 원)의 투자를 진행했다.

크래프톤 손현일 투자본부장은 “프라틸리피의 서적, 코믹스, 오디오 플랫폼를 통해 인도 현지 IP의 성장을 지켜보면서 인도 현지 IP가 인도 뿐 아니라 전 세계적으로 성공할 수 있다는 장기적인 잠재력을 믿게 됐다”며, “프라틸리피는 이미 웹소설 분야의 다국어 플랫폼을 보유하고 있기 때문에 향후 시장에서 크게 성장할 기업이라고 보고 있다”고 말했다.

  • 프라틸리피는 3,000만 명의 월간 활성 이용자(MAU)와 37만 명의 작가를 확보하고 있는 인도 최대 웹소설 플랫폼이다. 12개의 인도 언어로 서비스를 제공하고 있으며, 최근에는 웹소설 뿐만 아니라 일반서적, 애니메이션, TV시리즈 등 다양한 형태의 콘텐츠 제공을 위해 관련 기업들과의 협업을 가속화하고 있다. 또, 프라틸리피 FM, 프라틸리피 코믹스 등을 출시하며 서비스 범위도 확장 중이다.

3. 의약품 주문통합 플랫폼 ‘바로팜’, 팁스 프로그램 선정

의약품 주문통합 플랫폼 ‘바로팜’, 팁스 프로그램 선정

의약품 주문통합 플랫폼인 ‘바로팜’이 중소벤처기업부가 주관하는 민간투자주도형 기술창업지원(TIPS) 프로그램에 선정됐다.

현재 200여개 약국이 바로팜 서비스를 이용하고 있고 이번 투자를 통해 수도권 위주의 서비스에서 전국적인 서비스로 확대해 나갈 예정이며 올 하반기 1000개 약국에 바로팜 서비스를 제공하는 것을 목표로 하고 있다.

현직 약사이자 바로팜 김슬기 대표는 “바로팜은 의약품 주문통합 플랫폼으로서 업무에 지친 약사님들에게 간편한 주문 시스템을 제공하고 지속적으로 약국 주문 관련 불편한 부분을 약사님들과 함께 고민해 나갈 예정이다. 이를 통해 약국경영에 도움을 주는 다양한 서비스들을 선보일 것”이라고 말했다

  • 팁스: 팁스는 우수 기술을 보유한 유망 스타트업을 발굴해 정부가 2년 간 최대 7억 원을 지원 및 투자하는 대표적인 민간 투자 주도형 기술 창업 지원 프로그램이다.

  • 바로팜: 바로팜은 의약품을 주문하는 도매사이트들을 한 곳에서 관리하는 ‘의약품 주문 통합 솔루션’을 제공하는 플랫폼이다. 현재 의약품 통합 주문, 주문 알림톡 발송, 약국 관련 주문사이트 바로가기 통합 제공, 의약품 정보 식별 및 약물 상호작용 검색 기능 제공 등 다양한 서비스를 약국에 제공하고 있다.


[Spring Boot] JAVA 오버로딩과 오버라이딩

[Spring Boot] JAVA 오버로딩과 오버라이딩

자바의 Overloading & Overriding

자바에서 다형성을 지원하는 방법으로 메서드를 오버로딩, 오버라이딩을 할 수 있다.

  • 오버로딩(Overloading): 같은 이름의 메서드 여러개를 가지면서 매개변수의 유형과 개수가 다르도록 하는 것을 의미한다.
    • 리턴값만을 다르게 갖게 작성할 수 없다.

=> 오버로딩은 기존에 없던 새로운 메서드를 정의하는 것

  • 오버라이딩(Overriding): 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의해서 사용 하는 것을 의미한다.
    • 상위클래스의 메서드를 하위 클래스에서 재정의하는 것이다.
    • 메서드의 이름, 파라미터의 갯수, 타입이 동일해야 하며, 주로 상위 클래스의 동작을 상속받은 하위 클래스에서 변경하기 위해 사용된다.

=> 오버라이딩은 상속 받은 메서드의 내용만 변경하는 것

[Spring Boot] 데이터베이스 Update 하는 법

[Spring Boot] 데이터베이스 Update 하는 법

데이터베이스 Update하기

웹 브라우저에서 회원 수정을 하는 경우를 생각하며,

@PutMapping을 이용해서 주소를 만들어줬다. 이때 적은 주소는 @GetMapping의 주소와 동일한데, 스프링부트에서는 알아서 Get, Put을 구별해준다.

첫 번째 방법 (Save함수 사용)

주소에서 id를 받아온다. 이 id는 데이터베이스에 저장 된 id값을 불러오기 위함이다.

그리고 @ReqeustBody를 이용하여 Json 데이터를 요청하여, 이를 JavaObject로 변환한다.

SpringBoot에서는 MessageConverter가 Jackson 라이브러리를 사용하여 자동적으로 변환해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// email, password
@PutMapping("/dummy/user/{id}")
public User upadteUser(@PathVariable int id, @RequestBody User requestUser) { // Json 데이터를 요청 => Java Object(MessageConverter의 Jackson라이브러리로 변환해서 받음

User user = userRepository.findById(id).orElseThrow(() -> {
return new IllegalArgumentException("수정에 실패하였습니다.");
});
user.setPassword(requestUser.getPassword());
user.setEmail(requestUser.getEmail());
// save함수는 id를 전달하지 않으면 insert를 해주고,
// save함수는 id를 전달하면 해당 id에 대한 데이터가 있으면 update를 해주고
// save함수는 id를 전달하면 해당 id에 대한 데이터가 없으면 insert를 한다.

userRepository.save(user);
return null;
}

Select 때와 마찬가지로, 잘못 된 (없는) id값을 받았을 때를 방지하기 위해 IllegalArgumentException을 throw 할 수 있도록 한다.

정상적인 user객체에 수정하고자 했던 데이터(password와 email)을 set으로 수정해준다.

그리고 save함수를 이용하여 update해준다.


Save 함수, save 함수를 사용할 때

id를 전달하지 않으면 insert를 해주고,

id를 전달하고, 해당 id에 대한 데이터가 있으면 update를 해준다.

id를 전달하지만, 해당 id에 대한 데이터가 없으면 insert를 해준다.


두 번째 방법

@Transactional라는 annotaion을 사용해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// email, password
@Transactional
@PutMapping("/dummy/user/{id}")
public User upadteUser(@PathVariable int id, @RequestBody User requestUser) { // Json 데이터를 요청 => Java Object(MessageConverter의 Jackson라이브러리로) 변환해서 받음

User user = userRepository.findById(id).orElseThrow(() -> {
return new IllegalArgumentException("수정에 실패하였습니다.");
});
user.setPassword(requestUser.getPassword());
user.setEmail(requestUser.getEmail());

// 더티체킹
return user;
}

첫 번째 방법과 크게 다른 것은 없지만, @Transactional을 이용하면, Save함수를 사용하지 않아도 된다.

이를 Dirty Checking (더티체킹) 이라고 한다.

updateUser라는 함수가 실행될 때, Transaction이 실행되고, return이 될때 Transaction이 자동으로 종료되며, 자동 commit이 된다.


영속성 컨텍스트와 더티체킹에 대해서 공부해보자!

영속성 컨텍스트