import sys
N = int(sys.stdin.readline().strip())
A = list(map(int, sys.stdin.readline().split()))
A.sort()
result = 0defisGood(goal):
left, right = 0, N - 1while left < right:
if A[left] + A[right] == A[goal]:
if left == goal:
left += 1elif right == goal:
right -= 1else:
returnTrueelif A[left] + A[right] > A[goal]:
right -= 1elif A[left] + A[right] < A[goal]:
left += 1for i inrange(N):
result += 1if isGood(i) isTrueelse0print(result)
우선 함수를 만들고 그 함수를 기준으로 left 쪽으로 갈지, right 쪽으로 갈지 정하는 것이다.
이번 문제의 함수에서 반환하는 값은 공유기의 개수이다.
거리를 기준으로 공유기를 놓아보고, 만약 공유기가 더 필요하다면 거리를 늘리는 것이다.
import sys
N, M = map(int, sys.stdin.readline().split())
house = []
for i inrange(N):
house.append(int(sys.stdin.readline()))
house.sort()
defwifi(length):
result = 1
cur = house[0]
for i inrange(1, N):
if house[i] >= cur + length:
cur = house[i]
result += 1return result
left = 1
right = house[-1] - house[0]
while left <= right:
mid = (left + right) // 2
cnt = wifi(mid)
if cnt >= M:
left = mid + 1else:
right = mid - 1print(right)
import sys
N, M = map(int, sys.stdin.readline().split())
tree = list(map(int, sys.stdin.readline().split()))
defcut(height):
result = 0for i in tree:
result += max(0, i - height)
return result
left, right = 0, max(tree)
while left <= right:
mid = (left + right) // 2
cur_height = cut(mid)
if cur_height >= M:
left = mid + 1else:
right = mid - 1print(right)
publicclassCompletableFuture<T> implementsFuture<T>, CompletionStage<T>{
publicstatic <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier){
return asyncSupplyStage(ASYNC_POOL, supplier);
}
publicstatic CompletableFuture<Void> runAsync(Runnable runnable){
return asyncRunStage(ASYNC_POOL, runnable);
}
publicbooleancomplete(T value){
boolean triggered = completeValue(value);
postComplete();
return triggered;
}
publicbooleanisCompletedExceptionally(){
Object r;
return ((r = result) instanceof AltResult) && r != NIL;
}
publicstatic CompletableFuture<Void> allOf(CompletableFuture<?>... cfs){
return andTree(cfs, 0, cfs.length - 1);
}
publicstatic CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs){
int n; Object r;
if ((n = cfs.length) <= 1)
return (n == 0)
? new CompletableFuture<Object>()
: uniCopyStage(cfs[0]);
for (CompletableFuture<?> cf : cfs)
if ((r = cf.result) != null)
returnnew CompletableFuture<Object>(encodeRelay(r));
cfs = cfs.clone();
CompletableFuture<Object> d = new CompletableFuture<>();
for (CompletableFuture<?> cf : cfs)
cf.unipush(new AnyOf(d, cf, cfs));
// If d was completed while we were adding completions, we should// clean the stack of any sources that may have had completions// pushed on their stack after d was completed.if (d.result != null)
for (int i = 0, len = cfs.length; i < len; i++)
if (cfs[i].result != null)
for (i++; i < len; i++)
if (cfs[i].result == null)
cfs[i].cleanStack();
return d;
}
}
publicinterfaceCompletionStage<T> {
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);
public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn);
}
CompletionStage 인터페이스는 이렇게 구성이 되어 있다.
차례로 내려가면서 실행하기 때문에 각각 파이프 하나의 단계라고 생각하면 될 것이다.
저번 내용과 다르게, 결과를 직접적으로 가져올 수 없기 때문에 비동기 프로그래밍이 가능하게 된다.
또한 Non-blocking으로 프로그래밍하기 위해서는 별도의 쓰레드가 필요하다.
Completable은 내부적으로 FokJoinPool을 사용한다.
할당된 CPU 코어 - 1 에 해당하는 쓰레드를 관리하는 것이다.
이렇게 다른 쓰레드에서 실행이 되기 때문에 Non-blocking 프로그래밍도 가능하게 해준다.
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,
Executor executor);
위와는 다르게 Future가 종료되지 않았다면, thenAccept는 callee에서 실행이 되게 된다.
이를 통해, Async는 그냥 thread pool에서 가져와서 실행이 되며 Async가 아니면 stage의 상태에 따라 나뉘는 것을 볼 수 있다.
stage가 실행중이라면, 호출한 caller 쓰레드에서 실행이 된다.
stage가 실행중이 아니라면, 호출된 caller 쓰레드에서 실행이 되게 된다.
위에서 마지막에 있던 메서드 중에 파라미터가 하나 더 있던 메서드가 있었다.
executor를 넘겨주는 것인데, 해당 action이 실행될 쓰레드를 지정해주는 것이다.
@Slf4jpublicclassB{
@SneakyThrowspublicstaticvoidmain(String[] args){
var single = Executors.newSingleThreadExecutor();
var fixed = Executors.newFixedThreadPool(10);
log.info("start main");
CompletionStage<Integer> stage = CompletableFuture.supplyAsync(() -> {
log.info("supplyAsync");
return1;
});
stage
.thenAcceptAsync(i -> {
log.info("{} in thenAcceptAsync", i);
}, fixed).thenAcceptAsync(i -> {
log.info("{} in thenAcceptAsync", i);
}, single);
log.info("after thenAccept");
Thread.sleep(2000);
single.shutdown();
fixed.shutdown();
}
}
해당 코드를 실행해보면
이렇게 지정된 쓰레드에서 실행이 되는 것을 볼 수 있다.
thenApply[Async]
Function를 파라미터로 받는다.
이전 task로부터 T 타입의 값을 받아서 가공하고 U 타입의 값을 반환한다.
다음 task에게 반환했던 값이 전달된다.
값을 변형해서 전달해야 하는 경우 유용하다.
@FunctionalInterfacepublicinterfaceFunction<T, R> {
R apply(T t);
}
해당 Function을 파라미터로 받는다.
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,
Executor executor);
메서드가 다음과 같이 있다.
해당 메서드들을 하면서 확인해보자.
@Slf4jpublicclassC{
publicstaticvoidmain(String[] args)throws InterruptedException {
CompletionStage<Integer> stage = CompletableFuture.supplyAsync(() -> 1);
stage.thenApplyAsync(value -> {
var next = value + 1;
log.info("in thenApplyAsync : {}", next);
return next;
}).thenApplyAsync(value -> {
var next = "result: " + value;
log.info("in thenApplyAsync2 : {}", next);
return next;
}).thenApplyAsync(value -> {
var next = value.equals("result: 2");
log.info("in thenApplyAsync3 : {}", next);
return next;
}).thenAcceptAsync(value -> {
log.info("final: {}", value);
});
Thread.sleep(2000);
}
}
해당 코드를 실행하면 다음과 같다.
thenApply는 다른 타입을 주고 받는 것이 가능한 것을 볼 수 있다.
thenCompose[Async]
Function를 파라미터로 받는다.
이전 task로부터 T 타입의 값을 받아서 가공하고 U 타입의 CompletionStage를 반환한다.
반환한 CompletionStage가 done 상태가 되면 값을 다음 task에 전달한다.
다른 future를 반환해야 하는 경우 유용하다.
public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn,
Executor executor);
소수를 판정 할 때, 어차피 계산 한 부분은 안 할 거 같아서 굳이 에라토스테네스의 체를 쓰지는 않았다.
함수를 이용해서, 만약 길이가 N이라면 해당 수를 바로 출력하고 아니라면 뒤에 수를 계속 붙여주는 방법으로 풀었다.
어차피 앞 부분은 이미 소수일 테니까, 해당 수가 소수인지만 판별을 진행했다.
import sys
N = int(sys.stdin.readline().strip())
prime = [2, 3, 5, 7]
defis_prime(number):for i inrange(2, int(number ** 0.5) + 1):
if number % i == 0:
returnFalsereturnTruedefwow_prime(cur_number):iflen(str(cur_number)) == N:
print(cur_number)
else:
for t inrange(1, 10):
if t % 2 != 0and is_prime(cur_number * 10 + t):
wow_prime(cur_number * 10 + t)
for i in prime:
wow_prime(i)