ternary operator를 정의해버리는데 코드를 봐도 모르겠다. 세상엔 참 대단한 사람들이 많은듯.
http://stackoverflow.com/a/8790269/766330
(결론적으로 나는 그냥 ifelse()쓰기로 했음 ㅋㅋㅋ)
`?` <- function(x, y) {
xs <- as.list(substitute(x))
if (xs[[1]] == as.name("<-")) x <- eval(xs[[3]])
r <- eval(sapply(strsplit(deparse(substitute(y)), ":"), function(e) parse(text = e))[[2 - as.logical(x)]])
if (xs[[1]] == as.name("<-")) {
xs[[3]] <- r
eval.parent(as.call(xs))
} else {
r
}
}
assign(eg. )하는 데 bracket을 치는 수고를 감내할 수 있다면,
그러니까 아래와 같은 동작을 감내할 수 있다면
> y <- 1 ? 2*3 : 4
[1] 6
> y
[1] 1
> y <- (1 ? 2*3 : 4)
> y
[1] 6
더 간단하게,
`?` <- function(x, y)
eval(
sapply(
strsplit(
deparse(substitute(y)),
":"
),
function(e) parse(text = e)
)[[2 - as.logical(x)]])
2016년 7월 18일 월요일
2016년 7월 13일 수요일
is fibo
주어진 숫자가 fibonacci number인지를 알아보는 것이 목표인데, 처음부터 조금 쉽게 해보려고 삽질을 하다가 괜한 시간만 보냈다.
위키에도 있지만 \(5x^2 + 4\)나 \(5x^2 -4\)중 하나만 perfect square여도 \(x\)가 fibonacci number이다. 문제는 이런식으로 하려면 data type때문에 숫자가 조금만 커져도 풀 수가 없어진다는 점. 주어진 열자리 수가 fibonacci number인줄 알기 위해서는 \(5\times x \times x\)를 계산해야 하는데 금방 스무자리가 넘어간다. 아주 큰 수의 square root를 어떻게 계산해야 하는지는 좀 더 찬찬히 생각해 봐야 할 것 같다.
이 문제가 의외였던 점은, brutal force로 해도 열자리 정도에는 금방 도달한다는 점. 1,1,2,3,...으로 진행되는 squence에서 99번째면 서른자리1)에 도달하고 996번째면 300자리2)에 도달한다.
위키페이지를 보다가, ‘The Fibonacci Quarterly’라는 저널이 있다는 것도 알았다. 세상엔 참 별의별 저널이 다 있다.
1) 118842243771396506390315925504
2) 125567414904640701673643560436718962175164626371742219622314498637150513803703451854671685017464358374327500732525759393576618588167068051984194268453498923483608216111221456860403218028074661818882275572106013378713850874227329307333971218118090581030131208722889166027270662089679192033248503922688
위키에도 있지만 \(5x^2 + 4\)나 \(5x^2 -4\)중 하나만 perfect square여도 \(x\)가 fibonacci number이다. 문제는 이런식으로 하려면 data type때문에 숫자가 조금만 커져도 풀 수가 없어진다는 점. 주어진 열자리 수가 fibonacci number인줄 알기 위해서는 \(5\times x \times x\)를 계산해야 하는데 금방 스무자리가 넘어간다. 아주 큰 수의 square root를 어떻게 계산해야 하는지는 좀 더 찬찬히 생각해 봐야 할 것 같다.
이 문제가 의외였던 점은, brutal force로 해도 열자리 정도에는 금방 도달한다는 점. 1,1,2,3,...으로 진행되는 squence에서 99번째면 서른자리1)에 도달하고 996번째면 300자리2)에 도달한다.
위키페이지를 보다가, ‘The Fibonacci Quarterly’라는 저널이 있다는 것도 알았다. 세상엔 참 별의별 저널이 다 있다.
1) 118842243771396506390315925504
2) 125567414904640701673643560436718962175164626371742219622314498637150513803703451854671685017464358374327500732525759393576618588167068051984194268453498923483608216111221456860403218028074661818882275572106013378713850874227329307333971218118090581030131208722889166027270662089679192033248503922688
2016년 7월 12일 화요일
binary gap
binary gap문제.
이렇게 생겼다. (링크)아래는 python으로 짜본거.
from math import log
def tz(n): #trailing zeros
return int(log(n - (n&(n-1)), 2)) #= int(log(n& -n, 2))
def binarygap(n):
sol = 0
while True:
n = n >> (tz(n) + 1)
if n == 0 : break
sol = max(sol, tz(n))
return sol
위에 trailing zeros 얻는 과정(n- (n&(n-1)))이 약간 tricky한데, 천천히 생각해보면 알 수 있다.
아래는 n&-n의 계산된 몇가지 예시. 보면 대충 알 수 있다.
>>> for i in range(1, 40):
... print bin(i), bin(i & -i)
...
0b1 0b1
0b10 0b10
0b11 0b1
0b100 0b100
0b101 0b1
0b110 0b10
0b111 0b1
0b1000 0b1000
0b1001 0b1
0b1010 0b10
0b1011 0b1
0b1100 0b100
0b1101 0b1
0b1110 0b10
0b1111 0b1
0b10000 0b10000
0b10001 0b1
0b10010 0b10
0b10011 0b1
0b10100 0b100
0b10101 0b1
0b10110 0b10
0b10111 0b1
0b11000 0b1000
0b11001 0b1
0b11010 0b10
0b11011 0b1
0b11100 0b100
0b11101 0b1
0b11110 0b10
0b11111 0b1
0b100000 0b100000
0b100001 0b1
0b100010 0b10
0b100011 0b1
0b100100 0b100
0b100101 0b1
0b100110 0b10
0b100111 0b1
비트를 하나하나 순차적으로 검사해도 O(log n)이라 연산을 저렇게 tricky하게 해도 complexity의 이득은 없다. worst case에서는 둘 다 O(log n). best case에서 큰 차이가 난다. O(log log n)
비슷한 원리로, binary로 나타냈을 때 1이 몇개 나오는지 맞추는 문제도 있다.
python코드는 다음과 같다.
def howmany1s(n) :
count = 0
while(n >0):
n = n&(n-1)
count += 1
return count
2016년 7월 7일 목요일
\( \int_5^6 e^{x^{0.4889982575}} \)
\(\approx 10\)
심심해서.
유효숫자의 영향을 많이 받는 것 같다. CASIO계산기로 했을 때는 0.488998257396018이었고, 끝에 8을 7999999~로 바꿔도 답이 동일했다.
MATLAB을 가지고 해봤는데 이건 이상하게 결과가 변화가 없는 선이 어디까지인지 모르겠다. numerical integral인데 설마 precision이 \(\infty\)는 아닐 것이고...
integral(@(x) exp(x.^0.488998257408731679118929491778544615954161), 5, 6)
여기까지 해봤다. 저기서 소수 끝자리를 계속 늘려가면 9.99999999999999와 10 사이를 계속 오락가락 한다. 실행 전 format long e 해야 한다. 기본값은 short다.
밑줄 친 부분이 답이 서로 다른 부분인데, 셋 다 옳을 수는 없으므로 셋중에 적어도 둘은 값이 부정확한 것이다. Wolfram alpha로 해보면,
0.4889982574087317906738955163926...으로 10에 근접한다.
밑줄 친 부분부터 MATLAB과 다르나 보통 숫자는 mathematica가 더 정확하다고들 한다.
어찌되었건 계산기는 (계산결과 뿐 아니라)입력부터 소수 열째자리정도 부터는 신뢰하기 힘들다는 교훈.
심심해서.
유효숫자의 영향을 많이 받는 것 같다. CASIO계산기로 했을 때는 0.488998257396018이었고, 끝에 8을 7999999~로 바꿔도 답이 동일했다.
MATLAB을 가지고 해봤는데 이건 이상하게 결과가 변화가 없는 선이 어디까지인지 모르겠다. numerical integral인데 설마 precision이 \(\infty\)는 아닐 것이고...
integral(@(x) exp(x.^0.488998257408731679118929491778544615954161), 5, 6)
여기까지 해봤다. 저기서 소수 끝자리를 계속 늘려가면 9.99999999999999와 10 사이를 계속 오락가락 한다. 실행 전 format long e 해야 한다. 기본값은 short다.
밑줄 친 부분이 답이 서로 다른 부분인데, 셋 다 옳을 수는 없으므로 셋중에 적어도 둘은 값이 부정확한 것이다. Wolfram alpha로 해보면,
0.4889982574087317906738955163926...으로 10에 근접한다.
밑줄 친 부분부터 MATLAB과 다르나 보통 숫자는 mathematica가 더 정확하다고들 한다.
어찌되었건 계산기는 (계산결과 뿐 아니라)입력부터 소수 열째자리정도 부터는 신뢰하기 힘들다는 교훈.
2016년 7월 5일 화요일
같다/다르다
‘얼마만큼 같냐’와 ‘얼마만큼 다르냐’는 동전의 양면같이 서로 본질을 공유하는 듯 하면서도 막상 숫자로 나타내려면 아예 둘이 서로 다르다. ‘\(0\)만큼 다르다’는 직관적이지만, ‘\(0\)만큼 같다’거나 ‘\(10000\)만큼 같다’는 조금 이상하지 않은가. ‘\(\infty\)만큼 같다’도 이상하기는 마찬가지다.
영어
Since that time, Scholze, now 28, has risen to eminence in the broader mathematics community. Prize citations have called him “already one of the most influential mathematicians in the world” and “a rare talent which only emerges every few decades.” He is spoken of as a heavy favorite for the Fields Medal, one of the highest honors in mathematics.
출처: https://www.quantamagazine.org/20160628-peter-scholze-arithmetic-geometry-profile/
Prize citations는 뜻도 잘 이해가 안간다.
출처: https://www.quantamagazine.org/20160628-peter-scholze-arithmetic-geometry-profile/
Prize citations는 뜻도 잘 이해가 안간다.
2016년 6월 30일 목요일
Spiral Matrix
size nr×nc의 spiral matrix에서 (r, c)의 좌표에 있는 숫자N은 다음과 같다.
n1 = min(r, c, nr-1-r, nc-1-c)
n2 = (r == n1 || (nc-1-c) == n1)? c + r - 2*n1 : 2*nc + 2*nr - 6*n1 - r - c
N = n1*2*(nr+nc-2) - 4*n1*(n1-1) + n2
n1 = min(r, c, nr-1-r, nc-1-c)
n2 = (r == n1 || (nc-1-c) == n1)? c + r - 2*n1 : 2*nc + 2*nr - 6*n1 - r - c
N = n1*2*(nr+nc-2) - 4*n1*(n1-1) + n2
2016년 6월 27일 월요일
Clustering
http://link.springer.com/article/10.1007/s40745-015-0040-1
survey하나 링크.
survey하나 링크.
1. Classical
A. Partition
k-means, k-medoids, PAM, CLARA, CLARANS
not suitable for non-convex data
B. HIERARCHY
BIRCH(CF tree), CURE(random sampling, large scale clustering), ROCK(improvement of CURE. about enumeration type), Chameleon
C. Fuzzy
FCM: ‘object function’
FCS: distance function by multi-dimensional hypersphere
MM: Mountain function → find the center of cluster
relatively high accuracy.
easily drawn into local optimal.
D. Distribution
DBCLASD
same distribution → same cluster
GMM
several gaussian distributions, high scalablity.
E. Density
high density → same cluster
DBSCAN *
OPTICS : improvement of DBSCAN
1) radius of neighborhood
2) min number of pts in a neighborhood
Mean-Shift *
pros
high efficiency
arbitrary shape
cons
density에 따라 결과가 안좋을 수 있음
big size memory
sensitive to parameters
DENCLUE : large scale data clustering
F. GRAPH Theory
1) CLICK : min weight of division of the graph
2) MST(minimum spanning tree)-based clustering
pros
high efficiency
high accuracy
cons
time complexity grows as graph's complexity grows.
SM, NJW algorithm need to be considered
G. Grid
original data space → grid structure
1) STING
a. divided into many rectangular by constructing hierarchical structure
b. parallable
2) CLIQUE
grid based + density based
pros
low time complexity
high scalability
cons
accuracy-efficiency trade-off
wave cluster와 관련되어 있음
H. Fractal Theory
FC : change of any inner data of cluster does not have any influence on the instrinsic quality of the fractal dim. O(n)
sensitive to parameters
I. Model
1) Statistical learning
COBWEB : probability dist of each attr. is indenpendent
2) Neuralnet
a. SOM : build a mapping of dimension reduction.(assumption: there exists topology in the input)
b. ART : incremental algorithm. generates a new neuron.
time complexity : COBWEB < ART < SOM
2. MODERN
A. Kernel
kernel k-means
kernel SOM
kernel FCM
SVC : sphere in feature space → original data space (isoline: border of clusters)
MMC : hyperplane with maximum margin
MKC : improvement of MMC
pros
can sepearate overlapping clusters.
not need preliminary knowledge about topology of data
cons
not good for large scale data(time complexity high)
sensitive to kernels and there parameters
B. Ensemble
initial clustering → (consensus function) → final result.
어지간하면 그냥 제일 좋을듯.
C. Swarm
simulate the changing process of the biological population
time complexity high
easy to understand
low scalability
D. Quantum Theory
QC : getting potential energy by Schrodinger.
DQC: improvement of QC. time based Schrodinger Eq.
E. Spectral Graph
graph partitioning.
1) recursive spectral : SM (Normalized cut이용한 image segmentation과 비슷)
2) multiway spectral : NJW (feature space by k-largest eigenvalues of the Laplacian Matrix)
time complexity high
Not sensitive to outliers
number of clusters needed to be preset
F. Affinity Propagation (AP ★)
simple, clear idea
N is not deeded (N: number of clusters)
G. Density and Distance (DD ★)
arbitrary shape
insensitive to outliers(but sensitive to parameters)
time complexity high
H. Spatial Data
DBSCAN, STING, Wavecluster(parallel processing possible), CLARANS(sample based CLARA + clustering by PAM)
I. Data Stream
STREAM
CluStream ┐
HPStream ┼ incremental
DenStream ┘
J. Large Scale Data
4V ┬ large in volume
├ rich in variety
├ high in velocity
└ doubt in veracity(정직성, 진실성, 정확도)
1) sample
2) data merge
3) dimension reduction
4) parallel
2016년 6월 22일 수요일
2016년 6월 21일 화요일
top500.org
이름은 Sunway TaihuLight.
기존 1위보다 세배정도 빠르고, 중국의 자체 제작 칩을 사용했다고 한다.
그리고 이제는 top500에 미국의 컴퓨터보다 중국의 컴퓨터가 더 많다고 한다.
이제 우리 아이들이 영어가 아니라 중국어를 배워야 할 날이 멀지 않았다.
기존 1위보다 세배정도 빠르고, 중국의 자체 제작 칩을 사용했다고 한다.
그리고 이제는 top500에 미국의 컴퓨터보다 중국의 컴퓨터가 더 많다고 한다.
이제 우리 아이들이 영어가 아니라 중국어를 배워야 할 날이 멀지 않았다.
2016년 6월 20일 월요일
과학에 대한 불신
아툴 가완디의 칼텍 축사
뉴스페퍼민트에 나온 기사인데, 혹 링크가 사라질까봐 전문을 스크랩.
번역 전 원문 링크
밑줄은 직접 친 것.
칼텍이 제 역할을 잘 했다면 – 물론 그렇겠죠 – 여러분은 이제 모두 과학자입니다. 미안해요, 영문학도와 역사학도 여러분도 과학자입니다. 과학은 하나의 전공이나 분야가 아닙니다. 과학은 체계적으로 사고하겠다는 약속이며 가설을 검증하고 사실을 관찰함으로써 우주를 설명하고 지식을 쌓아 나가겠다는 맹세입니다. 문제는 이런 사고방식이 일반적인 사고방식이 아니라는 것입니다. 과학적 사고는 부자연스럽고 비직관적입니다. 과학적 사고는 학습에 의해서만 가능합니다. 과학에 의한 설명은 종교와 경험, 상식이 말해주는 지혜와 충돌합니다. 우리는 한 때 태양은 하늘을 가로질러 움직이며 추운 곳에 있으면 감기가 든다는 상식을 가지고 살았습니다. 그러나 과학적 사고는 이런 직감이 단지 가설에 불과함을 알아야한다고 가르칩니다. 가설은 실험에 의해 검증되어야만 합니다.
내가 오하이오의 집을 떠나 대학으로 진학해 가장 지적으로 당황했던 일은 내가 생각했던 세상의 작동방식이 – 자연세상이든 인간세상이든 – 얼마나 잘못된 것이었는 지를 발견한 것입니다. 나는 교수님과 동료 학생들의 도움으로 새로운 지식들을 쌓았습니다. 그리고 집으로 돌아와 부모님들께 그들이 잘못 알고 있던 – 심지어 애착을 가지고 있던 – 모든 사실들을 알려주었습니다. 그러나 그 순간에도 나는 그저 하나의 믿음들을 다른 믿음들로 대체했던 것 뿐이었습니다. 내가 과학자로서 가져야할 특정한 생각의 자세를 가지게 되는데에는 오랜 시간이 걸렸습니다. 물리학자 에드윈 허블은 1938년 칼텍 졸업연설에서, 과학자는 “건전한 회의적 사고, 판단을 미루는 자세, 그리고 올바른 상상력” 을 – 다른 이들의 생각에 대해서만이 아니라 자신의 생각에 대해서도 – 가져야 한다고 말했습니다. 과학자는 논쟁적인 자세가 아니라 실험적인 자세를 가져야 합니다.
학생이었던 나는 이런 자세가 하나의 사고방식 이상의 것으로 보였습니다. 그것은 하나의 존재 방식이었고, 특히 매우 이상한 존재 방식이었습니다. 과학자는 회의적이어야 하고 상상력을 가져야 하지만, 그것이 너무 과해서는 안됩니다. 판단을 미루어야 하지만, 동시에 계속 판단을 해 나가야 합니다. 즉, 과학자는 세상을 열린 자세로 관찰하며 사실을 모으고 자신의 예측과 그 예측에 반하는 주장을 모두 검증해야 합니다. 그 후 마음을 정하고 지금 가지고 있는 가설들을 각각 긍정하거나 부정해야 합니다. 그러나 또한 어떤 것도 확정된 사실은 아니며, 모든 지식은 단지 확률적으로 진실일 뿐이라는 사실을 받아들여야 합니다. 오늘의 진실을 부정하는 증거는 언제든지 등장할 수 있습니다. 허블은 이를 이렇게 멋지게 표현했습니다. “과학자는 끊임없이 사실을 진실에 가깝게 고쳐나감으로써 세상을 설명한다.”
과학적 태도가 갖는 힘은 어마어마합니다. 우리는 지난 한 세기 동안 평균 수명을 두 배로 늘였고, 지상의 부를 증가시켰으며, 자연과 우주에 대해 매우 깊게 이해하게 되었습니다. 그러나 과학은 아직 충분한 신뢰를 받고 있지 못합니다. 물론 과학이 완전하지 못하다는 것도 이유일 수 있습니다. 그러나 과학적 증거가 충분한 경우에도, 사람들은 이를 받아들이지 않으며, 때로 노골적으로 부정합니다. 예를 들어, 많은 이들이 수많은 증거에도 불구하고 백신이 자폐를 일으킨다고 (사실이 아닙니다), 총을 소유하는 것이 더 안전하다고 (사실이 아닙니다), 유전자 변형 농산물이 해롭다고(따져보면 이득이 더 많았습니다), 그리고 기후 변화가 일어나지 않는다고(일어나고 있습니다) 믿고 있습니다.
예를 들어 백신에 대한 공포는 수십 년 동안의 연구가 보여준 증거에도 불구하고 사라지지 않고 있습니다. 약 25년 전, 자폐와 티메로살이라는, 백신이 바이러스에 감염되지 않게 만드는 보존제 사이의 연관가능성을 보인 연구가 있었습니다. 그 연구는 잘못된 것으로 드러났지만, 공포는 사라지지 않았습니다. 과학자들은 수백건의 연구를 진행했지만 더 이상 연관성은 나타나지 않았습니다. 그럼에도 불구하고 공포는 여전했습니다. 어떤 나라에서는 보존제를 금지했으나 자폐증의 발병률에는 변화가 없었습니다. 그리고 여전히 공포는 존재했습니다. 영국에서 8명의 자폐 아와 그들이 맞은 홍역, 유행성 이하선염, 풍진의 백신 사이에 관계가 있다는 연구가 발표되었습니다. 그러나 그 연구는 저자가 데이터를 조작했고, 결과를 잘못 해석했기 때문에 취소되었습니다. 여전히 백신을 기피하는 사람들이 있으며, 지난 해 홍역과 이하선염이 발병해 미국, 캐나다, 유럽에서 수만명의 아이들이 병에 걸렸으며 죽음에 이르기도 했습니다.
사람들은 자신의 직관과 과학적 사실이 충돌할 때 자신의 직관을 더 신뢰합니다. 사람들은 이제 주변에서 홍역이나 이하선염에 걸리는 아이를 보지 못합니다. 반면, 자폐아들은 여전히 이웃 중에 있습니다. 그리고 어떤 자폐아의 어머니는 이렇게 말합니다. “백신을 맞기 전까지는 아무 문제가 없었는데 백신을 맞고 자폐아가 되고 말았죠.”
이제 여러분은 이들에게 상관관계가 인과관계가 아니라고 말해줄 수 있을겁니다. 아이들은 첫 몇 해 동안 두 세 달에 한 번씩 백신을 맞기 때문에 모든 질병은 어떤 백신을 맞은 뒤에 발생할 수 있습니다. 둘 사이에 과학적 증거가 없다고 말해줄 수도 있겠지요. 그러나 한 번 세상에 퍼진 아이디어를 사람들의 머리 속에서 완전히 지워버리는 것은 매우 어렵습니다. 특히 그들이 과학의 권위를 신뢰하지 않을 때는 더욱 그렇습니다. 그리고 오늘날, 우리는 과학의 권위가 크게 감소하고 있음을 보고 있습니다.
사회학자 고든 고차는 1974년부터 2010년 사이의 미국인들에 대한 설문조사를 바탕으로 매우 심각한 경향이 존재한다는 것을 발견했습니다. 그것은 교육 수준의 향상에도 불구하고 과학계에 대한 대중의 신뢰가 감소하고 있다는 것입니다. 특히 보수적인 이들에게 이런 경향이 심하며, 높은 교육수준의 보수적인 이들에게서 이런 흐름은 가장 크게 나타납니다. 1974년만 하더라도 대학을 졸업한 보수주의자들은 과학과 과학계를 가장 신뢰하는 집단이었습니다. 그러나 이제 그들은 가장 과학을 신뢰하지 않는 집단입니다.
오늘날 세상에는, “자신들만의 지식을 만들어 과학계의 권위와 출돌하는” 고차가 그들만의 문화적 영역을 가졌다고 설명한, 자신들을 특별하게 구별짓는 집단들이 있습니다. 예를 들어, 진화에 반대하는 종교 집단이 있으며, 기후 변화에 회의적인 산업 집단이 있습니다. 축적된 의학적 지식을 거부하는 이들이 보다 진보적인 이들 중에 있습니다. 이들은 모두 다 다르지만, 한 가지 사실에서 동일합니다. 그것은 자신만의 신성한 믿음 속에 머물며 이에 대한 질문을 허용하지 않는다는 것입니다.
이들도 자신들의 믿음을 지키기 위해 과학 자체의 권위를 부정하지는 않습니다. 이들은 과학계(scientific community)의 권위를 부정합니다. 이들도 이제 더 이상 자신들의 신성이 가진 권위를 주장하지 않습니다. 반대로 자신들이 더 진실한 과학의 권위를 가지고 있다고 주장합니다. 이는 문제를 매우 복잡하게 만듭니다. 우리는 이제 과학과 의사과학(pseudoscience)을 구별할 수 있어야 합니다.
과학의 수호자들은 의사과학자들의 방식을 다섯가지 특징적인 형태로 분류했습니다. 그들은 과학적 공감대가 이견을 억압하기 위한 것이라는 음모론을 펼칩니다. 그들은 제대로 된 경력을 밟지 못한 가짜 전문가를 내세워 다른 주장을 펼칩니다. 그들은 자신들의 입맛에 맞는 연구결과만을 가져와 마치 그 분야 전체를 믿을 수 없는 분야인 것처럼 꾸밉니다. 그들은 잘못된 비유를 들고, 궤변을 이용합니다. 그리고 그들은 비정상적으로 높은 연구기준을 세우며, 과학자들이 어떤 수준의 확실성을 달성했을 때 다른 의사과학자들이 다른 수준을 달성했다고 주장합니다.
그들의 접근 방식이 언제나 무용한 것은 아닙니다. 때로 비유는 도움이 되며, 더 높은 수준의 확실성 역시 필요합니다. 그러나 위의 전략들이 동시에 동원될 때, 우리는 이들이 과학적 주장을 하고 있지 않다는 사실을 알게 됩니다. 의사과학은 본질이 존재하지 않는 과학입니다.
이 문제를 해결할 수 있는 방법 – 곧, 과학이 세상을 설명하는 더 유용한 방법임을 보이는 것 – 역시 과학을 통해 제시되어 있습니다. 2011년, 두 명의 호주 연구자는 이와 관련해 “사실을 밝히다(The Debunking Handbook)”라는 책을 출간했습니다. 그 결과는 매우 인상적입니다. 사람들 앞에서 나쁜 과학을 반박하는 것은 효과가 없었습니다. 오히려 일반적으로 역효과를 낳았습니다. 나쁜 과학적 믿음과 모순되는 과학적 사실을 설명하는 것은 오히려 사람들이 그 믿음을 익숙하게 여기게 만들었고 추종자들의 확신을 강화시켰습니다. 사실 뇌는 정확히 이런 방식으로 작동합니다. 잘못된 정보는 뇌에 깊숙히 새겨집니다. 이는 그 정보가 그 사람이 생각하는 세상이 돌아가는 방식과 잘 맞아떨어지기 때문입니다. 따라서 그 오류만을 분리해내는 것은 불가능합니다. 오히려 그 사람이 가진 사고방식 – 그런 방식 자체가 없을 수도 있지만 – 에 고통스런 공백을 만들 뿐입니다.
그렇다면, 과학을 지지하는 이들은 어떻게 해야 할까요? 우리는 영원히 끝없는 논쟁을 벌일 수 밖에 없는 것일까요? 꼭 그런 것은 아닙니다. 사람들이 과학을 신뢰하게 만들 수 있는 방법에 대한 증거들도 발견되고 있습니다. 나쁜 과학에 대해 반박하는 것은 좋은 방법이 아닐 수 있지만 좋은 과학의 진실을 내세우는 것은 그렇지 않습니다. 그리고 그 사실을 설명하는 이야기를 포함하는 것은 더 효과적입니다. 예를 들어 백신에 대한 공포에 무엇이 잘못되었는지를 설명하기 보다 아이들에게 백신을 맞히는 것이 그렇지 않은 것보다 훨씬 더 아이들을 안전하게 만든다는 사실을 말해주는 것입니다. 어떤 증거가 있을까요? 과거 행해졌던 다양한 실험들에 의해 우리는 수많은 증거를 가지고 있습니다. 1989년에서 1991년 사이에 미국의 도시 빈민가 아이들은 백신을 맞지 못했습니다. 그때문에 오만 오천명의 아이들이 홍역에 걸렸고 123명이 사망했습니다.
다른 방법은 나쁜 과학이 사람들을 속이기 위해 주로 사용하는 전략을 사람들에게 알리는 것입니다. 나쁜 과학에는 패턴이 존재합니다. 따라서 사람들에게 그 패턴을 알려줌으로써 사람들이 과학적 지식을 더 신뢰하도록 만들 수 있습니다. 세상에 대한 과학적 이해를 가진다는 것은 기본적으로 세상의 수많은 정보 중 어떤 것을 신뢰할 것인지를 판단하는 것입니다. 한 사람이 모든 질문에 대해 모든 증거를 다 찾아보는 것은 불가능합니다. 오늘날 지식은 너무나 광대하고 복잡해, 과학자이든 아니든, 한 사람이 익힐 수 있는 지식에는 한계가 있습니다.
자신의 연구분야를 가장 기초적인 수준부터 하나 하나 설명할 수 있는 과학자는 오늘날 거의 존재하지 않습니다. 과학자들은 다른 과학자들이 이룬 지식과 기술에 의지합니다. 과학적 자세가 가진 힘과 지식은 특정 개인이 아니라 집단에 의한 것입니다. 우리가 “과학계”라고 말할 때, 우리는 매우 중요한 어떤 사실을, 곧 첨단과학은 지적 노동이 이루어지는, 복잡하게 얽힌 부서들을 가진 일종의 사회적 기업임을 의미하는 것입니다. 한 명의 과학자는 고집을 피울 수 있고, 자기 주장에 함몰될 수 있으며, 새로운 증거를 무시할 수도 있고, 자신의 오류를 전혀 개의치 않을 수도 있습니다. (그래서 막스 플랑크는 과학은 장례식 한 번에 그 만큼씩 진보한다고 말했지요.) 그러나 집단적인 노력에 의해 과학계는 아름다울 정도로 놀라운 자기 교정능력을 가지게 됩니다.
물론 과학계가 실제로 아름답지는 않습니다. 가까이서 본다면, 과학계는 엉망진창인 논문 심사과정과 엉터리로 쓰인 논문들, 편집자에게 날아오는 미묘하게 경멸적인 투서들, 명백하게 경멸적인 게시판의 댓글들, 그리고 학계의 잘난척 하는 성명서들 등 진실을 향해 나아간다고 보기에는 너무나 삐걱대는 수레입니다. 그러나 집단의 지성은 항상 앞으로 나아갑니다. 과학은 이제 모든 존재하는 영역에서 지식을 쌓아나가고 있습니다. 심지어 인문학에서도, 뇌과학과 컴퓨터 공학은 자유의지의 문제에서부터 예술과 문학이 시대에 따라 어떻게 진화되어 왔는지와 같은 문제에 이르기까지 다양한 문제에 대한 우리의 이해를 넓히고 있습니다.
이제 여러분들은 인류의 역사에서 가장 강력한 집단인 과학계의 일원이 되었습니다. 여러분은 과학에 대한 신뢰가 줄어들고 있는 이 시대에 다시 이를 세워나가야 할 책임을 지고 있습니다. 공공 보건분야에서 일하는 나는 과학을 매우 의심스러워하는 이들과 종종 마주칩니다. 이들은 언론인들이 “주류(mainstream)” 과학이라 이름지은(마치 다른 과학이 있는 것처럼 말이지요) 생리학, 영양학, 질병, 약학 등의 가장 기초적인 지식들 조차도 의심합니다. 대체로 이들은 가장 덜 배운 이들이 아니라 가장 많이 배운 이들입니다. 교육은 사람들에게 과학을 접하게 만들지만, 또한 이들을 보다 개인주의적이며 이데올로기적으로 만들어, 과학을 부정하게 만드는 효과도 있습니다.
문제는 오늘 여러분이 받게 되는 학위를 여러분들이 어떤 진실에 대한 특별한 권위로 오해하는 것입니다. 그러나 여러분들이 지금까지 배워온 것, 곧 진실을 찾아가는 과정이 어떠해야 하는지에 대한 이해가 훨씬 더 중요합니다. 그것은 한 사람이 아니라 한 집단의 사람들이 – 클 수록 더 좋습니다 – 호기심과 열정, 열린 자세, 그리고 원칙을 가지고 진실을 추구하는 것입니다. 다르게 말하면, 바로 과학자의 자세입니다.
여러분이 무엇을 생각하느냐보다, 어떻게 생각하느냐가 훨씬 더 중요합니다. 이를 이해하는 것은 오늘날 특히 그 무엇보다도 중요합니다. 왜냐하면, 우리는 과학자가 되는 것이 어떤 뜻인지만을 가지고 싸우고 있는 것이 아니기 때문입니다. 우리는 오늘날 시민이 된다는 것이 어떤 뜻인지를 가지고 싸우고 있습니다.
(뉴요커)
‘백신에 대한 공포’의 예를 최근에 읽어서 와 닿음. 2016년 6월 20일부터 초6~중1 여학생 47만명이 자궁경부암백신(HPV)을 무료접종 받게 되는데 그 백신의 부작용이 글의 주 내용이다.
과학이 과학자 한명의 마음가짐이나 자세가 아니라 과학자 집단이라는 거대한 사회적 기업의 일원이 되어 수행하는 작업이라는 부분이 마음에 든다. 누구도 스스로 자신의 무모순성을 입증할 수는 없는 법. 크로스체크는 언제나 필요하다.
과학계의 엉망진창인 모습 예시들이 마음에 든다. 적나라하고. ㅎㅎㅎㅎ
중간에 ‘과학을 신뢰하게 만들 수 있는 방법’은 어쩐지 꼼수같다는 생각이 든다. 사람들의 비이성적인 면이 과학을 불신하게 만든 것과 같은 방법으로 과학을 신뢰하게 만드는 것 아닌가 싶다. 물론 이것이 최선인지 아닌지는 별론으로 하고.(어쩌면 가능한 유일한 방법이 이것이라고 말하는 것일수도 있다.)
2016년 6월 17일 금요일
일반 공학용 계산기(scientific calculator) 3종 비교
\(\int_0^6 e^{x^3} dx\)
공학용 계산기관련 포스트를 보다가 내 계산기(CASIO fx-570ES PLUS)에서는 어느정도 걸리나 해 보니 2분정도 걸린다. ㅎㅎㅎㅎ 2분이라는 사실보다 2분을 기다리면 답이 나온다는게 더 신기하다. 중간에 overflow같은걸로 죽지 않고.
wolfram alpha 앱에 해보니 금방 나온다. 답이 조금 희한한데 근사치를 구하는 쉬운 공식이 있나보다. imaginary part가 나와서 이게 뭔가 하고 물어보니 그냥 오차라고 한다. 적분구간을 0. to 6. 이라고 주면 또 제대로 나온다고 한다.
아래는 570ES의 후속인 991EX
570ES와 디자인이 많이 다르지만 기본적인 기능은 같고, 건전지와 함께 태양광도 사용가능하도록 되어있다. 화면도 더 고해상도. 메뉴도 아이콘식으로 바뀌었지만 단지 UI변경에 불과하다. 그외 소소하게 바뀐점들이 많은데 행렬의 경우도 세개에서 네개로, 3×3에서 4×4로 limit도 커졌다. 하지만 이정도 변화야 거의 있으나 마나 한 것이니 다 그러려니 하면 될 것 같다. 다만 연산속도가 많이 향상되어 동일한 계산을 25초만에 해낸다.
아래 TI의 장점들을 보면 알겠지만, 아주 잘 만든 기계를 사소한 마무리때문에 명기의 반열에 올리지 못하는 것 같아 안타까울 정도다.
아래는 TI의 36X Pro
기본적으로 거의 모든 기능이나 연산능력이 570ES와 같다. 유효숫자 자리는 심지어 더 적다.(예를들어 \(\pi\)는 카시오의 경우 두 모델 다 내부적으로 3.14159265358980을 사용하지만 TI의 경우 3.141592653590을 사용한다. 열 다섯자리 vs. 열 세자리. 그래서 보다시피 위의 적분결과값도 약간 다르다. ) 연산능력이 991EX와는 비교가 되지 않아서 가격대 성능비는 매우 안좋은 편.(991EX가 몇천원 더 비싸다)
생긴것이 가장 마음에 들고 사용감도 좋다. 같은 키를 연속으로 누르면 기능이 순서대로 바뀌는 것도 마음에 든다. 예를들어 아래 사진에서 \(\pi^e_i\)키는 누를때마다 \(\pi, e, i\)가 차례로 나온다. 이렇게 하지 않으면 카시오 제품처럼 shift, alpha이렇게 meta키 두개를 만들어서 각 모드에 따라 다르게 동작하도록 만들어야 한다. TI제품은 그래서 alpha가 없다.)
버튼감이 좋고, 책상위에 놓았을 때 네 귀가 바닥에 밀착해서 버튼을 누를때도 계산기가 움직이지 않는다. 위의 카시오모델 두개는 모두 버튼을 누를 때마다 한 귀가 바닥에 살짝 닿았다 떨어지면서 딱딱 소리도 나고 약간씩 움직인다. 고무패딩 유무 차이인것 같다.
공학용 계산기관련 포스트를 보다가 내 계산기(CASIO fx-570ES PLUS)에서는 어느정도 걸리나 해 보니 2분정도 걸린다. ㅎㅎㅎㅎ 2분이라는 사실보다 2분을 기다리면 답이 나온다는게 더 신기하다. 중간에 overflow같은걸로 죽지 않고.
wolfram alpha 앱에 해보니 금방 나온다. 답이 조금 희한한데 근사치를 구하는 쉬운 공식이 있나보다. imaginary part가 나와서 이게 뭔가 하고 물어보니 그냥 오차라고 한다. 적분구간을 0. to 6. 이라고 주면 또 제대로 나온다고 한다.
아래는 570ES의 후속인 991EX
아래 TI의 장점들을 보면 알겠지만, 아주 잘 만든 기계를 사소한 마무리때문에 명기의 반열에 올리지 못하는 것 같아 안타까울 정도다.
아래는 TI의 36X Pro
기본적으로 거의 모든 기능이나 연산능력이 570ES와 같다. 유효숫자 자리는 심지어 더 적다.(예를들어 \(\pi\)는 카시오의 경우 두 모델 다 내부적으로 3.14159265358980을 사용하지만 TI의 경우 3.141592653590을 사용한다. 열 다섯자리 vs. 열 세자리. 그래서 보다시피 위의 적분결과값도 약간 다르다. ) 연산능력이 991EX와는 비교가 되지 않아서 가격대 성능비는 매우 안좋은 편.(991EX가 몇천원 더 비싸다)
생긴것이 가장 마음에 들고 사용감도 좋다. 같은 키를 연속으로 누르면 기능이 순서대로 바뀌는 것도 마음에 든다. 예를들어 아래 사진에서 \(\pi^e_i\)키는 누를때마다 \(\pi, e, i\)가 차례로 나온다. 이렇게 하지 않으면 카시오 제품처럼 shift, alpha이렇게 meta키 두개를 만들어서 각 모드에 따라 다르게 동작하도록 만들어야 한다. TI제품은 그래서 alpha가 없다.)
버튼감이 좋고, 책상위에 놓았을 때 네 귀가 바닥에 밀착해서 버튼을 누를때도 계산기가 움직이지 않는다. 위의 카시오모델 두개는 모두 버튼을 누를 때마다 한 귀가 바닥에 살짝 닿았다 떨어지면서 딱딱 소리도 나고 약간씩 움직인다. 고무패딩 유무 차이인것 같다.
카시오 제품중에는 scientific calculator로 분류되면서도 더욱 강력한 모델들이 있다. 홈페이지에는 ‘프로그래밍 가능모델’로 분류되어 있다.
아래는 1999년에 구입했던 9900GC. 위의 계산기들과는 다르게 graphic calcuator로 분류되고 기능도 많다. 행렬도 거의 무제한 사이즈로 되는듯. 몇십×몇십을 시험삼아 눌러봤는데 가능했다. 행렬 숫자도 훨씬 더 많았고.(위의 모델들은 행렬 서너개밖에 지원하지 않는다.) 연산이 실제로 가능한지는 해보지 않았지만, 입력이 가능한것 보면 느리게라도 연산또한 가능할 것이다. 위의 계산을 똑같이 해 보았는데 30초정도 걸렸고 정확도도 상당히 떨어졌다. 유효숫자 조절이 ‘공학용/과학용’ 선택 + ‘자릿수 조절’로 가능한듯 보였는데 무엇으로 해도 더 정확한 계산결과는 얻지 못했다. 아무래도 너무 옛날 물건이라 그런 것 같다. 홈페이지에서도 이 제품에 대한 정보를 얻을 수 없다. 요즘 가장 많이 나간다는 9860G II의 매뉴얼을 보니 적분할 때 numerical method를 정해주는 것 같은데, 이 모델은 그냥 보는대로 저렇게 넣는 방법이 다인것 같다. 물론 매뉴얼도 잃어버린지 오래라 확인은 불가.
2016년 6월 7일 화요일
브라우저 비교
소스보면 아주 간단한 기본적인 태그만을 사용했다.
아래 이미지 순서대로, 사파리, 크롬, 익스플로러9
가독성때문에 사파리를 쓰지 않을 수가 없는데, 그 이유가 잘 드러나는 웹페이지라서 포스팅.
2016년 5월 4일 수요일
remote desktop
vnc써도 되지만 귀찮고, xrdp설치하고 클라이언트 MS에서 뿌리는거 받아다가 붙으면 그냥 된다. 단 ubuntu에서 기본 gnome session은 잘 안듣는것 같았고 아래에 따라서 xfce4로 함. 역시 xubuntu
http://askubuntu.com/questions/91657/blank-desktop-when-logging-in-via-xrdp
http://askubuntu.com/questions/91657/blank-desktop-when-logging-in-via-xrdp
2016년 4월 12일 화요일
How Google Plans to Solve Artificial Intelligence
원문: https://www.technologyreview.com/s/601139/how-google-plans-to-solve-artificial-intelligence/
바둑 다음은 스타크래프트라고들 (국내)뉴스에 많이 나오던데, 기사에 따르면 다음은 미로찾기가 될것같다. 거기에 2~3년정도 주력할거라고 하고.(스타크래프트를 아예 안한다는 것이 아니라 바둑같은 빅게임으로 기획하는 것은 미로찾기라는 뜻)
신장kidney의 문제를 찾는 데에 현재 응용하고 있다고 한다. 어느정도 검증을 거치면 정말로 의학계에도 큰 변화가 찾아올 것 같다. 서서히든 갑작스럽게든.
추천시스템도 염두에 두고 있는듯 하다. 언제쯤 논문이나 해당 라이브러리를 내줄지 모르겠지만 아마 나도 그걸 받아 쓰게 될듯.
지능의 근본에 대해 설명하면서 'chunking'이라고 하는데, clustering을 고전적 의미가 아닌 방식으로 표현할 적당한 단어가 그것이어서 그랬을 것이다. 생각하는게 다들 비슷하구나. 결국 근본은 무엇이 같은가 혹은 그렇지 않은가이다. '비슷하다'는 아직 인간만이 가지는 개념이다.
바둑 다음은 스타크래프트라고들 (국내)뉴스에 많이 나오던데, 기사에 따르면 다음은 미로찾기가 될것같다. 거기에 2~3년정도 주력할거라고 하고.(스타크래프트를 아예 안한다는 것이 아니라 바둑같은 빅게임으로 기획하는 것은 미로찾기라는 뜻)
신장kidney의 문제를 찾는 데에 현재 응용하고 있다고 한다. 어느정도 검증을 거치면 정말로 의학계에도 큰 변화가 찾아올 것 같다. 서서히든 갑작스럽게든.
추천시스템도 염두에 두고 있는듯 하다. 언제쯤 논문이나 해당 라이브러리를 내줄지 모르겠지만 아마 나도 그걸 받아 쓰게 될듯.
지능의 근본에 대해 설명하면서 'chunking'이라고 하는데, clustering을 고전적 의미가 아닌 방식으로 표현할 적당한 단어가 그것이어서 그랬을 것이다. 생각하는게 다들 비슷하구나. 결국 근본은 무엇이 같은가 혹은 그렇지 않은가이다. '비슷하다'는 아직 인간만이 가지는 개념이다.
2016년 3월 24일 목요일
yum --nogpgcheck
if yum update or install halts with '~ package is not signed' error, try this option.
for example,
yum --nogpgcheck update
for example,
yum --nogpgcheck update
2016년 3월 22일 화요일
Reverse Shuffle Merge
심심풀이로 가끔 가서 노는 사이트. top coder의 easy version쯤 된다.
https://www.hackerrank.com/challenges/reverse-shuffle-merge
아직 어려운 문제들을 많이 접해보지 못해서 그런데, 이 문제가 지금까지 해본 것들중에 가장 시간을 많이 잡아먹은것 같다. 선수들은 이런거 10~20분에 끝날텐데. 답안 보고 좀 더 생각해봐야겠다.
테스트 케이스 세개. 문제 / 답 순서.
bdabaceadaedaaaeaecdeadababdbeaeeacacaba
aaaaaabaaceededecbdb
djjcddjggbiigjhfghehhbgdigjicafgjcehhfgifadihiajgciagicdahcbajjbhifjiaajigdgdfhdiijjgaiejgegbbiigida
aaaaabccigicgjihidfiejfijgidgbhhehgfhjgiibggjddjjd
cttpuwqslbtttyukcoorjbootbyrsktwxwmqtwrqrwqwctktuwtjtblwrujywyoyolkusucjuoyowswotckwultobwpwyuqymyuqxouuwuxwboqwykjuwjuukmkuytuquyubtpcytoqsyctwwtwrswptrroktmcwpstttblpuylsljmwjyqwtptktbjotqttyybyybyywlwtlyyxtqobttcuwxylswtytrcoytwtbuowkruoystqyyptwuuxykwljsuyutyboxwsutouruublwxowmomwmuoruwmbcustubtmmutswqtlmxuoyurumuwurpqsrwbltcoopyuckrbkctcqotwboxmjskcttwwrwlqptttlsuuymwuuucytytkmwutytlcojwswqlytyjwluwouuwcuowttoorwojuqwytsokwxtmtkoxtkwujsujcotbjwwutymwcmkoptwstywtwktowwwwutyckukwcjortwltocjpwwqtmmwjtwwpmwmbotsjulllmjsxwtlrpbkytwqttjuoowkuctqtwruowuwocwlyxylkroluysyktrmbtwwwkoswctojubrywpsxswqtptwcsbpmwourutttsluoocjwbcutwoptpcwjtpyubwtktuoytwytukrwtpuoktslxbspwymmuuuosluywtoyttwyujottrorcwtyywwwmtykyuytrwbwyoywtywrbpjwrkymlrwktwmwjrtwttwwwycswwuxsywrtutbptsowcucxuowuuwtrytuywxwtwuwcwlttqurottykbbwlbcxttoctwbxrurbxcrtqsyyucytwxpcuwywbbwskobwwjqjtsttsocwwxuryjputpwktjkoutyukywqywkspwopuroybqtyyokywultwmwomwxttbwwcutxoycotbptsttbwtwqutywjlxbpoplywljkqkwxttooqwwxtbtbccmbsocuuuptjultbowkuwpuspruqtoupltwmoutlyjjjqkxlwptctwwywtwjbcmuwkbltwyuormsuwtwxpxkkycspjjpmokuytbcowxxpuwwtxottjqpotwoxxwkwqwwswtwlowryplsoctstyorywyrlyrlltuyqtmowjpxtkttkowmtuttbolwpouwtxwwupucuuujckubwkuywkswkxuuybpsckuworqupqktujywwcywtuttbccottpuywkbukuwmjtsputkyjyrmwusllcbttlusmwwymybqwokspbolspokuwwwotrbwtwtopqpolsqrwkwtjottputboptuurlotxsttyywcktyymltmywobwwtpooqtopcbktbxcuwtxuuyyywulcqwxqywtkckutrtsttxtkyoccumttuwsumutrwryqwxktyjoxbtcuwmpjcqcwpxmwlumucstwykxoquylwxtuypwytkwkyltmtybsbywrwltytutyuruumumulpytouwttbuxtrlwkrowwywtywtjotbbosjwtutctuxutjbopywjturtqotubjwcwwtuymtyypxtyouubpjuotowsbcoowkwrwutwyuprltwuoquowurujtusutuwywtkpbwjoytcouyscbllrcoowmwbttywwwubpxptmstwtwwrutlmywmtbyucyujywqtjuxoltkwlsmuylwjktobwutyrpoxtwuytuuqclytutswwkcwoytuuywqrlyywsquypkltskwuoctmwwwwttwrtttuctcpwtkmjuqyouuoutjusuusuctwytkwcccuyylyluwxtocttrotywybwwmlokywtywurpocyttcrtpwwrqctwoxtrupoujqyutsqxtssurtyoqwuupwwyowtyutywtqyowjwwyukmqwuctjmtouuttwytwsxtlrurxotrttupswttjustwswtjxscjtusywwswkwpxkkcykluwyuruqtwwuwuutsubctmuprobjswmbstuqjytuytrtlbsytupubjyswrmoyowjwywxolqxukuwtxkktouccuomwptwtuctutwprubswcxscwcmcostwwttrumtoytowwulotwsqujrmopubuusuuwxwqwwlmyyttttklbtxoxwxttjwmwtumtptwlbuouowpswcytotropsuwwtmwuyutkryrwwtyxuyyyywwwyuttwucutcctwwtjjtxtmwttwoubtcsytwucwsbupttutjwwtxwutmwqttowwuxsbokkmujtwwuctwptytuwwowpwwoxoowtjutwruttcwwmbwowttplttbpubxlyuojwurwxptrjttwuyqttyuttstwotbywuwymtottptlsrbxjutbubtypwbcttjswuwywwutklttxwttttyukqpttykjtcwwpyxuxyopsswmxbyyulwuctokouwwkyowcwcwmsrojmswwbyokwyywcuwlxoymsrbbruotwotcwuqtwuqwqyuuytbsowbwlubyywxkwupuyosoxmsuqsyucqctwmpokstwtcrwytuuwjmupwtoowtycuockpxsypstktyttxkltycbpsrwwtuxqpommwwwtkmwsjmubuquccwwslwtwotjtwwtukowomojbwubwttptoowtubrbwrycxcpotttwjpooutuowbotuwuwjysuwsjlbtcstwbbwpobuyxstyjuxtjrutjtuuwustorprjuwbwsttkwuuwwwpmjcuctlowkxwwmttwtwxqmywusmyorjtptwoyswwqbpywkwkyxttocmcwujtqcrubskqjtoujouyuwtpmucutupcqttjymtbywtpyytotcluwutkyljmpqyowupsuxmuusjtkwwcqstjqwwruttcbttcptctowtomtuojoywutuktwwwoortpmxubljumwslocurlwttooustwyqptylytpmxukwytxrojltubtuusyttutssmkwyqojtrjquotwtwwppwwmctwytyytwtclkworwwbtusryuwowkostwwwwwwmxowbmoltutystxmpwwttttltyqxoybbutmotwqqutxprkmoyomqbjtttuupmjlpmwwxsstcottrwttlrwwptsybywtobwotoxxybowxurwroqcsyrpoqwuwuttutrmwwytwxuwkutbrtmmuosywobtuctcuxpwcxqsuowutusmywsbmttsyuuuuuttttwjtopytljomywtotytuuwsoyjkwlooowlyxxtopyyuwyutctjukubyqxpurwbkurwyrpswmktuubxooyqktcboucsywolkwoqoymtjktwoqrourxubuwwywlwujjwwwqwpyxuwrykujlutqocmwltpcmxstoxklqtutsotoxyututwtwtwwrwysumupyrwxlwwmwslslwboxwtbtlpwlxyqlttjubptmytmwbsoyuwjtttwlwpryumxkpcowkujowtltywuolwwotyutucysuqltttwjutoucowtpttwtwltjsostwwoktkwtwtptwrtyjobtutqrwwqtyqtuwyomttmymkqtrrjtwtyuxtxlutotpwyjwsojwtmpstrooowwocrwywyxpocuktmoylupstrpccooptucmtybwxowwuruulpywqpwkqtowswtttcromumuwbkwctpckqbyjttwrjbtxpwpwwjtcmwtuwcbxcxyuqttsxjtpulumwptoxmxyqybwcjpkuwcoxcbwtcowypttuquuosyurucbtywykwtouwtrskbltuwtjybtmquytjyxtkucscuwulwjxwbbwotswpqqkrpybuwwumtpoxlwykqurqcukrmutucctowytwtbpxwbjojkqwuyklwttytupqwopoqyyqmoybutbwuywujwqbowwlywmwwwumbcwbytusortwwuqmqbulwtkouqmutotstomwmbylwrkowwusrqcyboouwwklytowxwkttsrwootqxwswtsjwlolqobtucwpqwotpuqkwjtlcucwjjtcmkkxurybukqtybjjxuwttquswytojtwbytxwubuttuwtwswlwytmtquywtuuwupmwubqtuuxctottkojqbtxbuyqwsquutoqwctwwuwrwomtwowttuwsywuykuttwruoppwumutltwttwstusxuyqotypujtxwtuwukqtmmtuuywuctqyrttptpytbloplsmtuctmryoctqmtuwtoytmwtuopjkwtutckckswswowoutulxjwlosylyjuutttjcwuwousrowttwlwuxqqobmtwmcttwyuxubryjkoouossyjpoqrxrtrmtrsotbyplwrwtcypmqcttousypyrokscyjropxwtputjwyylobttwouuustqtrcwowysottptyoktuwspkujubyrtwtqutwqsbkuuccyjlmltblrtyqwxtuxbukmuoptojwcrtsocbywcttulmtukjqtsuswwuyuttrkywuwqqcpcruymkxoltyxwrsqcuotkwkwtroclumrxyulcosrwowutouqxttlwolkkquqtrouuuxswuwtotypulrkurltuomwubpymkwuttuwtwywpouoswtkluytttywutwwwytwumxpktquoutrotbbttuxptuouqwwmtutuussuttspruwouyolxqwtpyxmlylcwwrlktypwtulwwyqywjpluoswpyqtmpttouptstwxurtruwpjojlwtwqtsctoutsswyuxpxbtwwotyjouubwwuttbkuocootswcktqbukcbywutjwwmwukrljwyxwkqwlowmkwkpcmumtqwowkytlrwycyuwtcbyutrxrowtstytckqyubttotltkmcysuskrbtucttxwluulsttjutcjskmwklrymwutcuustxkwmyycbqjlquwmqwjwutwuwutwusosclkxtktjompkoputtobqwmlqljxltuojptkcwmcqpttoyjuuosltwloubrjwjttjtwttuwuoctsttowwwwjybytqmoqytwrtctswworbtjruluyoktlwtswtrwyjxtjtttobtpouuyutlqcotslrcwmkbwjtstwxospqjtlbkuujouoowtcywwuwjtpqjutwtotbqcwytbswuubtuuwbbjjqboutcuosuwtrtmtpbxpytutowybjwxuuwwtotwuxtywubwotutmtpqcxoyuucyowuxqtcwtltpslcwyuuucwctpowsxrtsssuwycywrtutrjbccmblytwtktltucmjtywwupxtttpyrtmtuytcbwymtybyyllrsujtrtjoucwqyxtkuywtcwotuxbmtxsuwwyqurysotccrwrttrqjwwumrtlwmoottoywurjcrwttyyutcwmotmkusotcrbwrltswrwjupwowlykwywwlwqttttwcuxttbuqtutsoclutyyuwwwklbupwybrctbpsjwybjqwobttlxywwwwjuwxorowyrurwywoocwwwtbkpkuourokpttxqsxpyrloryuwlwwwkwyutuqluwuowwtywttywtutoulotxwluwwtbottuowsuqltuwrwkbjwtwptyytpxttwkmyutyqsyobocwbtwwtwutwbpotyupocuwwrpqyjpoypwwomtolwqwcstymuulmxuuuyllpcwcppqwkcwubkjjymuxtbuuoytuyyoubbjtpyutwkttycywtykwttqllmxpuslkxutowkwusuxmqooxptmmcsorryqtuwuuxcjctjwywyjwmyuwtsxtyowbrjwutluqkkqortwtcrwsskkytytummwymlstwqykwuttwpjptyuxwyltyxubustwsjytooqmpctkpltwutotkbtpyjsuwkuquowmuwpjtwtmcmtsobwttoqcstwcqyjcuttjbkowwsutwswjqmtrotutwpluotxtrqmwjtbuwjwuwtttbtkwkomwqltcwtqkouojcttccuttuwkwwotbxurwkowtmtxmuwswpotwwtykxcucsuuwtsbpwbsuywjwboqsurxotrtbukplwbttyptuwuwwwoutusbwtytwtuwxtrspwutwxrutmwwyxtmpupowtrbwxwtywcxyljtuwtuttlpulctrywwttrwspyomottxjbmuysotqckrbyljyrukpolmkxwbcojcloycryybtwlqmyuoluwoqqbwwxjuxltpwrtyocowqkbqttujyrwyrtrqtujumrutlyuumurcwttwcoyqpwkumctwbtxjsktwwpwturbybuqwwotwuwwtwkstjmkbtymtbyyyrxtlupwyyyqwbrpurttmwuujuyowwwwottrqpwjuwutbtkjytrmwqtuoyyqbypwwwcxwtukowmuyotpwyjwoyouspbuluurtwuwtlwxjkscutukolcmtxtotkpjuoctuupxlslkswqwwoycrwttquooyuwlystuttwuctkyoobojyrcutowkpowwmwcomtuusrmosyyrxubttwcwuljutrotuxtttotptoowsuctojbcucrwyycouoxolktsyupswuytwbwtkwwwtbuwtxtcwtwxyywxtwctuqtwyytjtsokwtuorwwwoututttuuuttotowtotkuouwpwyujtooqykwqtuyuwypuytybouwotmtuwktowcwywsytutwtptpjjwmjktxtswqccmotbbwqyytotwrltrobcbcblyowtbxucwobmttwxscyoccwyluxytbuxwmjrmqmutttlmjyookywpqjwoxkwtwuwutotbsywttuyslbwuymouupwmbbxtubuypuyyyxrbtwwpqwctwuusqoytwytuoqkwjorjrqmttckrwljbuwurwtupuqybwpuukwtuqmwwwmwotuykyorsqqtwyypbobmymjukrwuwswoqbtxppyblbwtmjtutxcususootbytuybljlstttjtjyuwcwsoukwtuuywjkmbwpxoywytmoxjsmlmwjjojukstussswkoyllltpuwywtmtcwwwyosttlrrmsrultqpucqsxplxuslupqutrtybtowttuyxwwwkqtwyypytmuctuoxltwpwwyrtjubtuyuyytroloobyumqttobrtwcuxcccbqrjwuuttuykwubkqloootwytctxwypcutxuwytswttwbptrbwtyqtbmtwoxtcwccmotwrtrxoqcxuwmoootuqujubottxwkokcwycyqtqwuwpxyymouctrywuyktytlukujssuktwowwyctrtwtywlcctkttujpyrpkotqcwmrwwttybmssmbjwussbutmuluttutulmswlljtuxbwyujwkytytmxyltuxwtuomtoourswuuoyupkojlulutuktubuxwxttyquuxylwsumcuotwbuuukttttwjtjobtyjtusuoubctmtwwwswlcxpsojculowxcuwutktkwykwuwxkwotclccrwwwxwtjutotmtbtosusqtruobbtotswxtbrruywbwuwrctwysxjmlmsytljutmowwyqpwtjotybcwyoutyxqojxutkytqcctwmrwrubtwwutctkttwutwolwywrtrwmboulwtjcwubtoooxboutopswbqytywmwtwwqwptcottwwoscrytttwuomscbbbjqycuuomxusuubwxyctsowrpouqbjwwwxtuwqwstwjssckxoywwmpcrsttupuoqquuuqwxywrupuwktcttuukmcwuyuuortwysbtpqtttlqrtysssuowstcuwowupklokmcxuususkmktsyywkbwqkmtlbtkcwwouckpxjwoxujutkuttqmkwwqltpxwuuklwoojtcmtotkuqtwsytytructwjosujywwlsxyqtputyqryyukxupwtymwokyywuytoorwlpppybtpqstjlowswuwlywuwwtcpybjtostwwoqlwbwoklwlttulutqwowtqywwtbkwlwmwowtwwtupojwjmtwwpkcwcywmywuustqowtcttstyuqwtyllcywctmtywwqolrbjuostswtxttusoucmwtltsqckowwoupwywswllwotostlwsrjbtppwbobskcmsttmkuyowjtwctsomxoyttutlpyycxutlxwytmjuuoscuuqpwwttwwtwwlwwwkbowwttbtscuwmwkourboqqowlwqkpytwtocrtwbuyktqtlouxoomurructtlycywxswwpyustwmrswymwmwtqotuwowuwwbswbkpuwtrpuolsjyluquwpcwoywbpubpjullckkyxpwttypturwuutrrtwucsrstcuuuroutwmtxqyytybkpwjtlywjytumkwwysruumtcwycuuwqbrttxoutorwlumyyuoouoccwsptyqtyusukojqutrppjuosubwmwwpooquktyuybutpwbouwjtmostrtwqwwmbtoqyokputwtjbptywkytjbttqwwyukotlwoyoyopwtorxkjwuwttwxtttypktuclwtxsckoqtxytwtlttoctlswtqbucwkbwubxotkttcbtutottcttpuybqlwrojbwwoqwobysmxtpobltjoywlwkptukytpttymtltsxlpqbyuwlmycummltwpptttpwuwjojjwwsrqujyuttuujoopkjcuputjqwxjotcsbqwrottbtjwrbycoqbluyoutwtotosmktqtwtqwbsoxycurrxstjowuwuctjucjrtuwxskqjktuoxlqkxwtywrwwucbtukworttutprcbwsouupxytwmutuwykxwswrtulcywywprpotqcwsxosutkombtscotccyostwwtwrwuwpsujlwbqqrmutjrptxrtwoxcxuyptrkuuwxbuoywyrwmttujruwopowwuttkwwuuwtoqwctqwutwuttcxqbtcbyjtrotyskxqpxmjllumylcjkwlcotljqkyjsyojkowuturuojltwtolmmwukxbtksxsujuswooupttjtutyoupwqwutwmysupkukoyymywywomwwwccomtbcxyoqucjyjpwytybsowjkxytyttwjylurpkrtttsqttkutrtuwuwttttmuwxwxutookorcwkwstwttxuyywkuccwtwwtuuwyooktytktjutsousjbqulmrxwwwjwsocqtwwpttoykwypptbwjptklwlucrmbcwkyutobtwucwxlywxrsruywyumowwtmjbsmjjrtyblyttcwoutwtqsyxxultuyuqwrqwwupmqwwotsytomjqtcuwutscxkokwxwtttubuwjtujxttluuwwotwruuwywcktkmyryywtusotjttouwowbuuwtwjswuwpocoucobkrtwttytrywtwttulbxjpywsosxtbrocjuptytcwttmowtsuwrpjpmumqtljwjclttoquuprwjwqswutjbwtwtbortwcbtxtwswswpopywbcouwtwlbujxucyrwctwuyjptutowksyutkrwutupkklwojutucsowquttsulllwxppotuoktubrtopttmkbtmwmwkttopwpbkyxbuwkbjwyutmtwotsostswuxyjqqwlxutucltutxwtumyopjwlowwwttuwtopotuulwuowutottkppwotocwwxtbcusywwqwxtwtkytquttuwyujttusqwwcwmpttcllyrsxwuobrtmtbqptwqytplwyuwmtyltbcrwubrwxtwtqmkwkwptkmuujlwutqukwpyjrtxwsstmutuqytmpxkypulwortyswtuxwsukyruqbtostbbtyyyubttusjukwmmwstcyo
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccjjcjcjtjjltjottccktjotjlqlmqottjtktcosttjqmqjqcmwkxtctuwlkwjctujttluulwxttcutrksuscktltottuqcttstworxrtuctwucwrltkwowqtmuckwkmwlwqkwxywjlrkuwmwwjtuwyckuqtcwstcoukttuwwuujytowwtxpxuywsstuotcstqwtwljojpwurtruxwtstpuottmtqypwsouljwyqywwlutwpytklrwwclylmxyptwqxloyuowurpsttussuututmwwquoutpxutttortuouqtkpxmuwtywwwtuwytttyulktwsouopwywtwuttuwkmypuwmoutlrukrlupytotwuwsxuuuortquqkklowlttxquotuwowrsocluyxrmulcortwkwktoucqsrwxytloxkmyurccqqwuwykrttuyuwwsustqjkutluttcwycostrcwjotoukuxutxwqytrltlljyccuuksqwtuqtwtryujukpswutkoytpttosywowcrtqtsuuuowttolyywjtuptwxporjycskorypysuottcqmpyctwrwlpytosrtmrtrxrqopjyssouoojyruxuywttcmwtmoqqxuwlwttworsuowuwcjtttuujylysolwjxlutuowowswsckctutwkjpoutwmtyotwutmqtcoyrmtcutmslpoltyptpttryqtcuwyuutmmtqkuwutwxtjupytoqyuxsutswttwtltumuwppourwttukyuwyswuttwowtmowrwuwwtcwqotuuqswqyuxtqjokttotcxuutquwmpuwuutwyuqtmtywlwswtwuttuuwxtywtjotywsuqttwuxjjytqkuyruxkkmctjjwcucltjwkquptowqpwcutoqlolwjstwswxqtoowrsttkwxwotylkwwuooycqrsuwwokrwlymwmotstotumquoktwluqmquwwtrosutywcmuwwwmwylwwoqwjuwyuwtuyomqyyqopowqputyttwlkyuwqkjojwxptwtywotccutumrkucqruqkywlxoptmuwwuyprkqqpwstowwxjwluwucscuktxyjtyuqmtyjtwutlksrtwuotwkywytcuruysouuquttpywoctwcxocwukpjcwyqyxmxotpwmuluptjxsttquyxcxcwutwmctjwwpwpxtjrwttjyqkcptcwkwumumorctttwswotqkwpqwypluuruwwoxwytmcutpooccprtspulyomtkucopxywywrcowwooortspmtwjoswjywptotulxtxuytwtjrrtqkmymttmoywutqytqwwrqtutojytrwtptwtwktkowwtsosjtlwtwttptwocuotujwtttlqusycutuytowwlouwytltwojukwocpkxmuyrpwlwtttjwuyoswmtymtpujttlqyxlwplttwxowlslswmwwlxwrypumusywrwwtwtwtutuyxotostutqlkxotsxmcptlwmcoqtuljukyrwuxypwqwwwjjuwlwywwuuxruorqowtkjtmyoqowklowyscuoctkqyooxuutkmwsprywrukwrupxqyukujtctuywuyypotxxylwooolwkjyoswuutytotwymojltypotjwttttuuuuuysttmswymsutuwousqxcwpxuctcutowysoummtrtukwuxwtywwmrtuttuwuwqopryscqorwruxwoyxxotowotwyystpwwrlttwrttoctssxwwmpljmpuutttjqmoyomkrpxtuqqwtomtuyoxqytlttttwwpmxtsytutlomwoxmwwwwwwtsokwowuyrsutwwrowklctwtyytywtcmwwppwwtwtouqjrtjoqywkmsstuttysuututljorxtywkuxmptylytpqywtsuoottwlrucolswmujluxmptroowwwtkutuwyojoutmotwotctpcttctturwwqjtsqcwwktjsuumxuspuwoyqpmjlyktuwulctotyyptwytmyjttqcputucumptwuyuojuotjqksurcqtjuwcmcottxykwkwypqwwsyowtptjroymsuwymqxwtwttmwwxkwoltcucjmpwwwuuwkttswwujrprotsuwuutjturjtxujytsxyuopwwtsctljswusyjwuwutowoutuoopjwtttopcxcyrwrutwootpttwuwjomowokutwwtjtowtwlswwccuquumjswmktwwwmmopqxutwwrspcytlkxttytktspysxpkcoucytwootwpumjwuutywrctwtskopmwtcqcuysqusmxosoyupuwkxwyyulwwostyuuyqwquwtquwctowtourrsmyoxlwucwyywkoywwsmjorsmwcwcwoykwwuokotcuwluyyxmwsspoyxuxypwwctjkyttpqkuyttttwxttlktuwwywuwsjttcwpytutujxrsltpttotmywuwytowtsttuyttqyuwttjrtpxwruwjouylxupttlpttwowmwwctturwtujtwooxowwpwowwutytpwtcuwwtjumkkosxuwwottqwmtuwxtwwjtuttpuswcuwtysctuowttwmtxtjjtwwtcctucuwttuywwwyyyyuxytwwryrktuyuwmtwwusportotycwspwououlwtptmutwmwjttxwxoxtlkttttyymlwwqwxwuusuuupomrjuqswtoluwwotyotmurttwwtsocmcwcsxcwsurpwtutcutwtpwmouccuotkkxtwukuxqloxwywjwoyomrwsyjuputysltrtyutyjqutsmwsjorpumtcustuuwuwwtquruywulkyckkxpwkwswwysutjcsxjtwswtsujttwsputtrtoxrurltxswtywttuuotmjtcuwqmkuywwjwoyqtwytuytwoywwpuuwqoytrusstxqstuyqjuopurtxowtcqrwwptrcttycopruwytwykolmwwywytorttcotxwulylyyucccwktywtcusuusujtuouuoyqujmktwpctcutttrwttwwwwmtcouwkstlkpyuqswyylrqwyuutyowckwwstutylcquutyuwtxoprytuwotkjwlyumslwktloxujtqwyjuycuytmwymlturwwtwtsmtpxpuwwwyttwmwoocrllcsyuoctyojwpktwywutusutjuruwouqouwtlrpuywtuwrwkwoocswotoujpuuoytxpyytmyutwwcwjutoqtrutjwypojtuxutctutwjsotojtwytwywworkwlrtxuttwuotyplumumuuruytutytlwrwysytmtlykwktywpyutxwlyuqoxkywtscumulwmxpwcqcjpmwuctxojytkxwqyrwrtumuswuttmuccoyktxttstrtukcktwyqxwqcluwyyyuuxtwucxtkcpotqooptwwowymtlmyytkcwyyttsxtolruutpotupttojtwkwrqslopqpotwtwrtowwwukopslopskowqymywwmsulttcllsuwmryjyktupstjmwukukwyupttoccttutwycwwyjutkqpuqrowukcspyuuxkwskwyukwukcjuuucupuwwxtwuopwlottutmwokttktxpjwomtqyutllrylrywyroytstcoslpyrwolwtwswwqwkwxxowtopqjttoxtwwupxxwoctyukompjjpscykkxpxwtwusmrouywtlkwumcjwtwywwtctpwlxkqjjjyltuomwtlpuotqurpsupwukwotlujtpuuucosmccttxwwqoottxwkqkjlwylpopxljwytuqwtwttstptocyoxtucwwttxwmowmwtluwykoyytqyorupowpskwyqwykuytuokjtkwptupjyruxwwcosttstjqjwwokswwywucpxwtycuyysqtrcxrurxwtcottxclwkyttoruqttlwcwuwtwxwyutyrtwuuwouxcucwostptutrwysxuwwscywwwttwtrjwmwtkwrlmykrwjprwytwyoywwrtyuykytmwwwyytwcrorttojuywttyotwyulsouuummywpsxlstkouptwrkutywtyoutktwuyptjwcptpowtucwjcooulsttturuowmpscwtptqwsxspwyrujotcwsokwwwtmrtkysyulorklyxylwcowuwourwtqtcukwooujttqwtykprltwxsjmlllujstomwmpwwtjwmmtqwwpjcotlwtrojcwkukcytuwwwwotkwtwytswtpokmcwmytuwwjtocjusjuwktxoktmtxwkostywqujowroottwoucwuuowulwjytylqwswjocltytuwmktytycuuuwmyuusltttpqlwrwwttcksjmxowtoqctckrkcuypooctlwrsqpruwumuruyouxmltqwstummtutsucmwuroumwmomwoxwluuruotuswxoytuyusjlwkyxuuwtpyyqtsyourkwoutwtyocrtytwslyxwucttoqtxyyltwlwyyyyyyttqtojtktptwqyjwmjlslyupltttspwcmtkorrtpwsrwtwwtcysqotycptuyuqutyukmkuujwujkywqowxuwuuoxquymyquywpwotluwktowswoyoujusukloyoywyjurwltjtwutktwqwrqrwtqmwxwtksrytoojrookuytttlsqwuptt
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;
const int CHARMAX=26;
bool incl(int* stat, int* remain) {
for(int i=0 ; i<CHARMAX; i++)
if(stat[i] > remain[i])
return false;
return true;
}
int nextidx(string &s, int idx, int* stat, int* remain) {
int smallidx = idx;
int tmpremain[CHARMAX];
for(int j=0; j<CHARMAX; j++) tmpremain[j]= remain[j];
for(int i=idx; i<s.size(); i++) {
if(stat[s[i]-'a'] > 0 && s[i]<s[smallidx]) {
if(incl(stat, tmpremain)) {
smallidx = i;
}
}
tmpremain[s[i]-'a']--;
}
return smallidx;
}
int main() {
string s;
cin >> s;
int stat[CHARMAX], remain[CHARMAX];
for(int i=0; i<CHARMAX; i++)
stat[i] = 0;
for(int i=0; i<s.size(); i++)
stat[s[i]-'a']++;
for(int i=0; i<CHARMAX; i++) {
remain[i] = stat[i];
stat[i] /= 2;
}
string ans;
for(int i=0; i<s.length(); i++) {
int ni = nextidx(s, i, stat, remain);
char thechar = s[ni];
if(stat[thechar-'a']-- > 0) ans += thechar;
if(ans.size() == s.length()/2) break;
for(int j=i; j<=ni; j++)
remain[s[j]-'a']--;
i = ni;
}
cout << ans << endl;
return 0;
}
https://www.hackerrank.com/challenges/reverse-shuffle-merge
아직 어려운 문제들을 많이 접해보지 못해서 그런데, 이 문제가 지금까지 해본 것들중에 가장 시간을 많이 잡아먹은것 같다. 선수들은 이런거 10~20분에 끝날텐데. 답안 보고 좀 더 생각해봐야겠다.
테스트 케이스 세개. 문제 / 답 순서.
bdabaceadaedaaaeaecdeadababdbeaeeacacaba
aaaaaabaaceededecbdb
djjcddjggbiigjhfghehhbgdigjicafgjcehhfgifadihiajgciagicdahcbajjbhifjiaajigdgdfhdiijjgaiejgegbbiigida
aaaaabccigicgjihidfiejfijgidgbhhehgfhjgiibggjddjjd
cttpuwqslbtttyukcoorjbootbyrsktwxwmqtwrqrwqwctktuwtjtblwrujywyoyolkusucjuoyowswotckwultobwpwyuqymyuqxouuwuxwboqwykjuwjuukmkuytuquyubtpcytoqsyctwwtwrswptrroktmcwpstttblpuylsljmwjyqwtptktbjotqttyybyybyywlwtlyyxtqobttcuwxylswtytrcoytwtbuowkruoystqyyptwuuxykwljsuyutyboxwsutouruublwxowmomwmuoruwmbcustubtmmutswqtlmxuoyurumuwurpqsrwbltcoopyuckrbkctcqotwboxmjskcttwwrwlqptttlsuuymwuuucytytkmwutytlcojwswqlytyjwluwouuwcuowttoorwojuqwytsokwxtmtkoxtkwujsujcotbjwwutymwcmkoptwstywtwktowwwwutyckukwcjortwltocjpwwqtmmwjtwwpmwmbotsjulllmjsxwtlrpbkytwqttjuoowkuctqtwruowuwocwlyxylkroluysyktrmbtwwwkoswctojubrywpsxswqtptwcsbpmwourutttsluoocjwbcutwoptpcwjtpyubwtktuoytwytukrwtpuoktslxbspwymmuuuosluywtoyttwyujottrorcwtyywwwmtykyuytrwbwyoywtywrbpjwrkymlrwktwmwjrtwttwwwycswwuxsywrtutbptsowcucxuowuuwtrytuywxwtwuwcwlttqurottykbbwlbcxttoctwbxrurbxcrtqsyyucytwxpcuwywbbwskobwwjqjtsttsocwwxuryjputpwktjkoutyukywqywkspwopuroybqtyyokywultwmwomwxttbwwcutxoycotbptsttbwtwqutywjlxbpoplywljkqkwxttooqwwxtbtbccmbsocuuuptjultbowkuwpuspruqtoupltwmoutlyjjjqkxlwptctwwywtwjbcmuwkbltwyuormsuwtwxpxkkycspjjpmokuytbcowxxpuwwtxottjqpotwoxxwkwqwwswtwlowryplsoctstyorywyrlyrlltuyqtmowjpxtkttkowmtuttbolwpouwtxwwupucuuujckubwkuywkswkxuuybpsckuworqupqktujywwcywtuttbccottpuywkbukuwmjtsputkyjyrmwusllcbttlusmwwymybqwokspbolspokuwwwotrbwtwtopqpolsqrwkwtjottputboptuurlotxsttyywcktyymltmywobwwtpooqtopcbktbxcuwtxuuyyywulcqwxqywtkckutrtsttxtkyoccumttuwsumutrwryqwxktyjoxbtcuwmpjcqcwpxmwlumucstwykxoquylwxtuypwytkwkyltmtybsbywrwltytutyuruumumulpytouwttbuxtrlwkrowwywtywtjotbbosjwtutctuxutjbopywjturtqotubjwcwwtuymtyypxtyouubpjuotowsbcoowkwrwutwyuprltwuoquowurujtusutuwywtkpbwjoytcouyscbllrcoowmwbttywwwubpxptmstwtwwrutlmywmtbyucyujywqtjuxoltkwlsmuylwjktobwutyrpoxtwuytuuqclytutswwkcwoytuuywqrlyywsquypkltskwuoctmwwwwttwrtttuctcpwtkmjuqyouuoutjusuusuctwytkwcccuyylyluwxtocttrotywybwwmlokywtywurpocyttcrtpwwrqctwoxtrupoujqyutsqxtssurtyoqwuupwwyowtyutywtqyowjwwyukmqwuctjmtouuttwytwsxtlrurxotrttupswttjustwswtjxscjtusywwswkwpxkkcykluwyuruqtwwuwuutsubctmuprobjswmbstuqjytuytrtlbsytupubjyswrmoyowjwywxolqxukuwtxkktouccuomwptwtuctutwprubswcxscwcmcostwwttrumtoytowwulotwsqujrmopubuusuuwxwqwwlmyyttttklbtxoxwxttjwmwtumtptwlbuouowpswcytotropsuwwtmwuyutkryrwwtyxuyyyywwwyuttwucutcctwwtjjtxtmwttwoubtcsytwucwsbupttutjwwtxwutmwqttowwuxsbokkmujtwwuctwptytuwwowpwwoxoowtjutwruttcwwmbwowttplttbpubxlyuojwurwxptrjttwuyqttyuttstwotbywuwymtottptlsrbxjutbubtypwbcttjswuwywwutklttxwttttyukqpttykjtcwwpyxuxyopsswmxbyyulwuctokouwwkyowcwcwmsrojmswwbyokwyywcuwlxoymsrbbruotwotcwuqtwuqwqyuuytbsowbwlubyywxkwupuyosoxmsuqsyucqctwmpokstwtcrwytuuwjmupwtoowtycuockpxsypstktyttxkltycbpsrwwtuxqpommwwwtkmwsjmubuquccwwslwtwotjtwwtukowomojbwubwttptoowtubrbwrycxcpotttwjpooutuowbotuwuwjysuwsjlbtcstwbbwpobuyxstyjuxtjrutjtuuwustorprjuwbwsttkwuuwwwpmjcuctlowkxwwmttwtwxqmywusmyorjtptwoyswwqbpywkwkyxttocmcwujtqcrubskqjtoujouyuwtpmucutupcqttjymtbywtpyytotcluwutkyljmpqyowupsuxmuusjtkwwcqstjqwwruttcbttcptctowtomtuojoywutuktwwwoortpmxubljumwslocurlwttooustwyqptylytpmxukwytxrojltubtuusyttutssmkwyqojtrjquotwtwwppwwmctwytyytwtclkworwwbtusryuwowkostwwwwwwmxowbmoltutystxmpwwttttltyqxoybbutmotwqqutxprkmoyomqbjtttuupmjlpmwwxsstcottrwttlrwwptsybywtobwotoxxybowxurwroqcsyrpoqwuwuttutrmwwytwxuwkutbrtmmuosywobtuctcuxpwcxqsuowutusmywsbmttsyuuuuuttttwjtopytljomywtotytuuwsoyjkwlooowlyxxtopyyuwyutctjukubyqxpurwbkurwyrpswmktuubxooyqktcboucsywolkwoqoymtjktwoqrourxubuwwywlwujjwwwqwpyxuwrykujlutqocmwltpcmxstoxklqtutsotoxyututwtwtwwrwysumupyrwxlwwmwslslwboxwtbtlpwlxyqlttjubptmytmwbsoyuwjtttwlwpryumxkpcowkujowtltywuolwwotyutucysuqltttwjutoucowtpttwtwltjsostwwoktkwtwtptwrtyjobtutqrwwqtyqtuwyomttmymkqtrrjtwtyuxtxlutotpwyjwsojwtmpstrooowwocrwywyxpocuktmoylupstrpccooptucmtybwxowwuruulpywqpwkqtowswtttcromumuwbkwctpckqbyjttwrjbtxpwpwwjtcmwtuwcbxcxyuqttsxjtpulumwptoxmxyqybwcjpkuwcoxcbwtcowypttuquuosyurucbtywykwtouwtrskbltuwtjybtmquytjyxtkucscuwulwjxwbbwotswpqqkrpybuwwumtpoxlwykqurqcukrmutucctowytwtbpxwbjojkqwuyklwttytupqwopoqyyqmoybutbwuywujwqbowwlywmwwwumbcwbytusortwwuqmqbulwtkouqmutotstomwmbylwrkowwusrqcyboouwwklytowxwkttsrwootqxwswtsjwlolqobtucwpqwotpuqkwjtlcucwjjtcmkkxurybukqtybjjxuwttquswytojtwbytxwubuttuwtwswlwytmtquywtuuwupmwubqtuuxctottkojqbtxbuyqwsquutoqwctwwuwrwomtwowttuwsywuykuttwruoppwumutltwttwstusxuyqotypujtxwtuwukqtmmtuuywuctqyrttptpytbloplsmtuctmryoctqmtuwtoytmwtuopjkwtutckckswswowoutulxjwlosylyjuutttjcwuwousrowttwlwuxqqobmtwmcttwyuxubryjkoouossyjpoqrxrtrmtrsotbyplwrwtcypmqcttousypyrokscyjropxwtputjwyylobttwouuustqtrcwowysottptyoktuwspkujubyrtwtqutwqsbkuuccyjlmltblrtyqwxtuxbukmuoptojwcrtsocbywcttulmtukjqtsuswwuyuttrkywuwqqcpcruymkxoltyxwrsqcuotkwkwtroclumrxyulcosrwowutouqxttlwolkkquqtrouuuxswuwtotypulrkurltuomwubpymkwuttuwtwywpouoswtkluytttywutwwwytwumxpktquoutrotbbttuxptuouqwwmtutuussuttspruwouyolxqwtpyxmlylcwwrlktypwtulwwyqywjpluoswpyqtmpttouptstwxurtruwpjojlwtwqtsctoutsswyuxpxbtwwotyjouubwwuttbkuocootswcktqbukcbywutjwwmwukrljwyxwkqwlowmkwkpcmumtqwowkytlrwycyuwtcbyutrxrowtstytckqyubttotltkmcysuskrbtucttxwluulsttjutcjskmwklrymwutcuustxkwmyycbqjlquwmqwjwutwuwutwusosclkxtktjompkoputtobqwmlqljxltuojptkcwmcqpttoyjuuosltwloubrjwjttjtwttuwuoctsttowwwwjybytqmoqytwrtctswworbtjruluyoktlwtswtrwyjxtjtttobtpouuyutlqcotslrcwmkbwjtstwxospqjtlbkuujouoowtcywwuwjtpqjutwtotbqcwytbswuubtuuwbbjjqboutcuosuwtrtmtpbxpytutowybjwxuuwwtotwuxtywubwotutmtpqcxoyuucyowuxqtcwtltpslcwyuuucwctpowsxrtsssuwycywrtutrjbccmblytwtktltucmjtywwupxtttpyrtmtuytcbwymtybyyllrsujtrtjoucwqyxtkuywtcwotuxbmtxsuwwyqurysotccrwrttrqjwwumrtlwmoottoywurjcrwttyyutcwmotmkusotcrbwrltswrwjupwowlykwywwlwqttttwcuxttbuqtutsoclutyyuwwwklbupwybrctbpsjwybjqwobttlxywwwwjuwxorowyrurwywoocwwwtbkpkuourokpttxqsxpyrloryuwlwwwkwyutuqluwuowwtywttywtutoulotxwluwwtbottuowsuqltuwrwkbjwtwptyytpxttwkmyutyqsyobocwbtwwtwutwbpotyupocuwwrpqyjpoypwwomtolwqwcstymuulmxuuuyllpcwcppqwkcwubkjjymuxtbuuoytuyyoubbjtpyutwkttycywtykwttqllmxpuslkxutowkwusuxmqooxptmmcsorryqtuwuuxcjctjwywyjwmyuwtsxtyowbrjwutluqkkqortwtcrwsskkytytummwymlstwqykwuttwpjptyuxwyltyxubustwsjytooqmpctkpltwutotkbtpyjsuwkuquowmuwpjtwtmcmtsobwttoqcstwcqyjcuttjbkowwsutwswjqmtrotutwpluotxtrqmwjtbuwjwuwtttbtkwkomwqltcwtqkouojcttccuttuwkwwotbxurwkowtmtxmuwswpotwwtykxcucsuuwtsbpwbsuywjwboqsurxotrtbukplwbttyptuwuwwwoutusbwtytwtuwxtrspwutwxrutmwwyxtmpupowtrbwxwtywcxyljtuwtuttlpulctrywwttrwspyomottxjbmuysotqckrbyljyrukpolmkxwbcojcloycryybtwlqmyuoluwoqqbwwxjuxltpwrtyocowqkbqttujyrwyrtrqtujumrutlyuumurcwttwcoyqpwkumctwbtxjsktwwpwturbybuqwwotwuwwtwkstjmkbtymtbyyyrxtlupwyyyqwbrpurttmwuujuyowwwwottrqpwjuwutbtkjytrmwqtuoyyqbypwwwcxwtukowmuyotpwyjwoyouspbuluurtwuwtlwxjkscutukolcmtxtotkpjuoctuupxlslkswqwwoycrwttquooyuwlystuttwuctkyoobojyrcutowkpowwmwcomtuusrmosyyrxubttwcwuljutrotuxtttotptoowsuctojbcucrwyycouoxolktsyupswuytwbwtkwwwtbuwtxtcwtwxyywxtwctuqtwyytjtsokwtuorwwwoututttuuuttotowtotkuouwpwyujtooqykwqtuyuwypuytybouwotmtuwktowcwywsytutwtptpjjwmjktxtswqccmotbbwqyytotwrltrobcbcblyowtbxucwobmttwxscyoccwyluxytbuxwmjrmqmutttlmjyookywpqjwoxkwtwuwutotbsywttuyslbwuymouupwmbbxtubuypuyyyxrbtwwpqwctwuusqoytwytuoqkwjorjrqmttckrwljbuwurwtupuqybwpuukwtuqmwwwmwotuykyorsqqtwyypbobmymjukrwuwswoqbtxppyblbwtmjtutxcususootbytuybljlstttjtjyuwcwsoukwtuuywjkmbwpxoywytmoxjsmlmwjjojukstussswkoyllltpuwywtmtcwwwyosttlrrmsrultqpucqsxplxuslupqutrtybtowttuyxwwwkqtwyypytmuctuoxltwpwwyrtjubtuyuyytroloobyumqttobrtwcuxcccbqrjwuuttuykwubkqloootwytctxwypcutxuwytswttwbptrbwtyqtbmtwoxtcwccmotwrtrxoqcxuwmoootuqujubottxwkokcwycyqtqwuwpxyymouctrywuyktytlukujssuktwowwyctrtwtywlcctkttujpyrpkotqcwmrwwttybmssmbjwussbutmuluttutulmswlljtuxbwyujwkytytmxyltuxwtuomtoourswuuoyupkojlulutuktubuxwxttyquuxylwsumcuotwbuuukttttwjtjobtyjtusuoubctmtwwwswlcxpsojculowxcuwutktkwykwuwxkwotclccrwwwxwtjutotmtbtosusqtruobbtotswxtbrruywbwuwrctwysxjmlmsytljutmowwyqpwtjotybcwyoutyxqojxutkytqcctwmrwrubtwwutctkttwutwolwywrtrwmboulwtjcwubtoooxboutopswbqytywmwtwwqwptcottwwoscrytttwuomscbbbjqycuuomxusuubwxyctsowrpouqbjwwwxtuwqwstwjssckxoywwmpcrsttupuoqquuuqwxywrupuwktcttuukmcwuyuuortwysbtpqtttlqrtysssuowstcuwowupklokmcxuususkmktsyywkbwqkmtlbtkcwwouckpxjwoxujutkuttqmkwwqltpxwuuklwoojtcmtotkuqtwsytytructwjosujywwlsxyqtputyqryyukxupwtymwokyywuytoorwlpppybtpqstjlowswuwlywuwwtcpybjtostwwoqlwbwoklwlttulutqwowtqywwtbkwlwmwowtwwtupojwjmtwwpkcwcywmywuustqowtcttstyuqwtyllcywctmtywwqolrbjuostswtxttusoucmwtltsqckowwoupwywswllwotostlwsrjbtppwbobskcmsttmkuyowjtwctsomxoyttutlpyycxutlxwytmjuuoscuuqpwwttwwtwwlwwwkbowwttbtscuwmwkourboqqowlwqkpytwtocrtwbuyktqtlouxoomurructtlycywxswwpyustwmrswymwmwtqotuwowuwwbswbkpuwtrpuolsjyluquwpcwoywbpubpjullckkyxpwttypturwuutrrtwucsrstcuuuroutwmtxqyytybkpwjtlywjytumkwwysruumtcwycuuwqbrttxoutorwlumyyuoouoccwsptyqtyusukojqutrppjuosubwmwwpooquktyuybutpwbouwjtmostrtwqwwmbtoqyokputwtjbptywkytjbttqwwyukotlwoyoyopwtorxkjwuwttwxtttypktuclwtxsckoqtxytwtlttoctlswtqbucwkbwubxotkttcbtutottcttpuybqlwrojbwwoqwobysmxtpobltjoywlwkptukytpttymtltsxlpqbyuwlmycummltwpptttpwuwjojjwwsrqujyuttuujoopkjcuputjqwxjotcsbqwrottbtjwrbycoqbluyoutwtotosmktqtwtqwbsoxycurrxstjowuwuctjucjrtuwxskqjktuoxlqkxwtywrwwucbtukworttutprcbwsouupxytwmutuwykxwswrtulcywywprpotqcwsxosutkombtscotccyostwwtwrwuwpsujlwbqqrmutjrptxrtwoxcxuyptrkuuwxbuoywyrwmttujruwopowwuttkwwuuwtoqwctqwutwuttcxqbtcbyjtrotyskxqpxmjllumylcjkwlcotljqkyjsyojkowuturuojltwtolmmwukxbtksxsujuswooupttjtutyoupwqwutwmysupkukoyymywywomwwwccomtbcxyoqucjyjpwytybsowjkxytyttwjylurpkrtttsqttkutrtuwuwttttmuwxwxutookorcwkwstwttxuyywkuccwtwwtuuwyooktytktjutsousjbqulmrxwwwjwsocqtwwpttoykwypptbwjptklwlucrmbcwkyutobtwucwxlywxrsruywyumowwtmjbsmjjrtyblyttcwoutwtqsyxxultuyuqwrqwwupmqwwotsytomjqtcuwutscxkokwxwtttubuwjtujxttluuwwotwruuwywcktkmyryywtusotjttouwowbuuwtwjswuwpocoucobkrtwttytrywtwttulbxjpywsosxtbrocjuptytcwttmowtsuwrpjpmumqtljwjclttoquuprwjwqswutjbwtwtbortwcbtxtwswswpopywbcouwtwlbujxucyrwctwuyjptutowksyutkrwutupkklwojutucsowquttsulllwxppotuoktubrtopttmkbtmwmwkttopwpbkyxbuwkbjwyutmtwotsostswuxyjqqwlxutucltutxwtumyopjwlowwwttuwtopotuulwuowutottkppwotocwwxtbcusywwqwxtwtkytquttuwyujttusqwwcwmpttcllyrsxwuobrtmtbqptwqytplwyuwmtyltbcrwubrwxtwtqmkwkwptkmuujlwutqukwpyjrtxwsstmutuqytmpxkypulwortyswtuxwsukyruqbtostbbtyyyubttusjukwmmwstcyo
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccjjcjcjtjjltjottccktjotjlqlmqottjtktcosttjqmqjqcmwkxtctuwlkwjctujttluulwxttcutrksuscktltottuqcttstworxrtuctwucwrltkwowqtmuckwkmwlwqkwxywjlrkuwmwwjtuwyckuqtcwstcoukttuwwuujytowwtxpxuywsstuotcstqwtwljojpwurtruxwtstpuottmtqypwsouljwyqywwlutwpytklrwwclylmxyptwqxloyuowurpsttussuututmwwquoutpxutttortuouqtkpxmuwtywwwtuwytttyulktwsouopwywtwuttuwkmypuwmoutlrukrlupytotwuwsxuuuortquqkklowlttxquotuwowrsocluyxrmulcortwkwktoucqsrwxytloxkmyurccqqwuwykrttuyuwwsustqjkutluttcwycostrcwjotoukuxutxwqytrltlljyccuuksqwtuqtwtryujukpswutkoytpttosywowcrtqtsuuuowttolyywjtuptwxporjycskorypysuottcqmpyctwrwlpytosrtmrtrxrqopjyssouoojyruxuywttcmwtmoqqxuwlwttworsuowuwcjtttuujylysolwjxlutuowowswsckctutwkjpoutwmtyotwutmqtcoyrmtcutmslpoltyptpttryqtcuwyuutmmtqkuwutwxtjupytoqyuxsutswttwtltumuwppourwttukyuwyswuttwowtmowrwuwwtcwqotuuqswqyuxtqjokttotcxuutquwmpuwuutwyuqtmtywlwswtwuttuuwxtywtjotywsuqttwuxjjytqkuyruxkkmctjjwcucltjwkquptowqpwcutoqlolwjstwswxqtoowrsttkwxwotylkwwuooycqrsuwwokrwlymwmotstotumquoktwluqmquwwtrosutywcmuwwwmwylwwoqwjuwyuwtuyomqyyqopowqputyttwlkyuwqkjojwxptwtywotccutumrkucqruqkywlxoptmuwwuyprkqqpwstowwxjwluwucscuktxyjtyuqmtyjtwutlksrtwuotwkywytcuruysouuquttpywoctwcxocwukpjcwyqyxmxotpwmuluptjxsttquyxcxcwutwmctjwwpwpxtjrwttjyqkcptcwkwumumorctttwswotqkwpqwypluuruwwoxwytmcutpooccprtspulyomtkucopxywywrcowwooortspmtwjoswjywptotulxtxuytwtjrrtqkmymttmoywutqytqwwrqtutojytrwtptwtwktkowwtsosjtlwtwttptwocuotujwtttlqusycutuytowwlouwytltwojukwocpkxmuyrpwlwtttjwuyoswmtymtpujttlqyxlwplttwxowlslswmwwlxwrypumusywrwwtwtwtutuyxotostutqlkxotsxmcptlwmcoqtuljukyrwuxypwqwwwjjuwlwywwuuxruorqowtkjtmyoqowklowyscuoctkqyooxuutkmwsprywrukwrupxqyukujtctuywuyypotxxylwooolwkjyoswuutytotwymojltypotjwttttuuuuuysttmswymsutuwousqxcwpxuctcutowysoummtrtukwuxwtywwmrtuttuwuwqopryscqorwruxwoyxxotowotwyystpwwrlttwrttoctssxwwmpljmpuutttjqmoyomkrpxtuqqwtomtuyoxqytlttttwwpmxtsytutlomwoxmwwwwwwtsokwowuyrsutwwrowklctwtyytywtcmwwppwwtwtouqjrtjoqywkmsstuttysuututljorxtywkuxmptylytpqywtsuoottwlrucolswmujluxmptroowwwtkutuwyojoutmotwotctpcttctturwwqjtsqcwwktjsuumxuspuwoyqpmjlyktuwulctotyyptwytmyjttqcputucumptwuyuojuotjqksurcqtjuwcmcottxykwkwypqwwsyowtptjroymsuwymqxwtwttmwwxkwoltcucjmpwwwuuwkttswwujrprotsuwuutjturjtxujytsxyuopwwtsctljswusyjwuwutowoutuoopjwtttopcxcyrwrutwootpttwuwjomowokutwwtjtowtwlswwccuquumjswmktwwwmmopqxutwwrspcytlkxttytktspysxpkcoucytwootwpumjwuutywrctwtskopmwtcqcuysqusmxosoyupuwkxwyyulwwostyuuyqwquwtquwctowtourrsmyoxlwucwyywkoywwsmjorsmwcwcwoykwwuokotcuwluyyxmwsspoyxuxypwwctjkyttpqkuyttttwxttlktuwwywuwsjttcwpytutujxrsltpttotmywuwytowtsttuyttqyuwttjrtpxwruwjouylxupttlpttwowmwwctturwtujtwooxowwpwowwutytpwtcuwwtjumkkosxuwwottqwmtuwxtwwjtuttpuswcuwtysctuowttwmtxtjjtwwtcctucuwttuywwwyyyyuxytwwryrktuyuwmtwwusportotycwspwououlwtptmutwmwjttxwxoxtlkttttyymlwwqwxwuusuuupomrjuqswtoluwwotyotmurttwwtsocmcwcsxcwsurpwtutcutwtpwmouccuotkkxtwukuxqloxwywjwoyomrwsyjuputysltrtyutyjqutsmwsjorpumtcustuuwuwwtquruywulkyckkxpwkwswwysutjcsxjtwswtsujttwsputtrtoxrurltxswtywttuuotmjtcuwqmkuywwjwoyqtwytuytwoywwpuuwqoytrusstxqstuyqjuopurtxowtcqrwwptrcttycopruwytwykolmwwywytorttcotxwulylyyucccwktywtcusuusujtuouuoyqujmktwpctcutttrwttwwwwmtcouwkstlkpyuqswyylrqwyuutyowckwwstutylcquutyuwtxoprytuwotkjwlyumslwktloxujtqwyjuycuytmwymlturwwtwtsmtpxpuwwwyttwmwoocrllcsyuoctyojwpktwywutusutjuruwouqouwtlrpuywtuwrwkwoocswotoujpuuoytxpyytmyutwwcwjutoqtrutjwypojtuxutctutwjsotojtwytwywworkwlrtxuttwuotyplumumuuruytutytlwrwysytmtlykwktywpyutxwlyuqoxkywtscumulwmxpwcqcjpmwuctxojytkxwqyrwrtumuswuttmuccoyktxttstrtukcktwyqxwqcluwyyyuuxtwucxtkcpotqooptwwowymtlmyytkcwyyttsxtolruutpotupttojtwkwrqslopqpotwtwrtowwwukopslopskowqymywwmsulttcllsuwmryjyktupstjmwukukwyupttoccttutwycwwyjutkqpuqrowukcspyuuxkwskwyukwukcjuuucupuwwxtwuopwlottutmwokttktxpjwomtqyutllrylrywyroytstcoslpyrwolwtwswwqwkwxxowtopqjttoxtwwupxxwoctyukompjjpscykkxpxwtwusmrouywtlkwumcjwtwywwtctpwlxkqjjjyltuomwtlpuotqurpsupwukwotlujtpuuucosmccttxwwqoottxwkqkjlwylpopxljwytuqwtwttstptocyoxtucwwttxwmowmwtluwykoyytqyorupowpskwyqwykuytuokjtkwptupjyruxwwcosttstjqjwwokswwywucpxwtycuyysqtrcxrurxwtcottxclwkyttoruqttlwcwuwtwxwyutyrtwuuwouxcucwostptutrwysxuwwscywwwttwtrjwmwtkwrlmykrwjprwytwyoywwrtyuykytmwwwyytwcrorttojuywttyotwyulsouuummywpsxlstkouptwrkutywtyoutktwuyptjwcptpowtucwjcooulsttturuowmpscwtptqwsxspwyrujotcwsokwwwtmrtkysyulorklyxylwcowuwourwtqtcukwooujttqwtykprltwxsjmlllujstomwmpwwtjwmmtqwwpjcotlwtrojcwkukcytuwwwwotkwtwytswtpokmcwmytuwwjtocjusjuwktxoktmtxwkostywqujowroottwoucwuuowulwjytylqwswjocltytuwmktytycuuuwmyuusltttpqlwrwwttcksjmxowtoqctckrkcuypooctlwrsqpruwumuruyouxmltqwstummtutsucmwuroumwmomwoxwluuruotuswxoytuyusjlwkyxuuwtpyyqtsyourkwoutwtyocrtytwslyxwucttoqtxyyltwlwyyyyyyttqtojtktptwqyjwmjlslyupltttspwcmtkorrtpwsrwtwwtcysqotycptuyuqutyukmkuujwujkywqowxuwuuoxquymyquywpwotluwktowswoyoujusukloyoywyjurwltjtwutktwqwrqrwtqmwxwtksrytoojrookuytttlsqwuptt
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;
const int CHARMAX=26;
bool incl(int* stat, int* remain) {
for(int i=0 ; i<CHARMAX; i++)
if(stat[i] > remain[i])
return false;
return true;
}
int nextidx(string &s, int idx, int* stat, int* remain) {
int smallidx = idx;
int tmpremain[CHARMAX];
for(int j=0; j<CHARMAX; j++) tmpremain[j]= remain[j];
for(int i=idx; i<s.size(); i++) {
if(stat[s[i]-'a'] > 0 && s[i]<s[smallidx]) {
if(incl(stat, tmpremain)) {
smallidx = i;
}
}
tmpremain[s[i]-'a']--;
}
return smallidx;
}
int main() {
string s;
cin >> s;
int stat[CHARMAX], remain[CHARMAX];
for(int i=0; i<CHARMAX; i++)
stat[i] = 0;
for(int i=0; i<s.size(); i++)
stat[s[i]-'a']++;
for(int i=0; i<CHARMAX; i++) {
remain[i] = stat[i];
stat[i] /= 2;
}
string ans;
for(int i=0; i<s.length(); i++) {
int ni = nextidx(s, i, stat, remain);
char thechar = s[ni];
if(stat[thechar-'a']-- > 0) ans += thechar;
if(ans.size() == s.length()/2) break;
for(int j=i; j<=ni; j++)
remain[s[j]-'a']--;
i = ni;
}
cout << ans << endl;
return 0;
}
2016년 3월 21일 월요일
random , shuffle.
C++을 쓰다 보면 C보다 참 쉽게 느껴지다가도 이런거 보면 자바따라가나 싶기도 하고.
string shuffle 예제. (출처)
string shuffle(string a) {
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(a.begin(), a.end(), default_random_engine(seed));
cout << "shuffle : " << a << endl;
return a;
}
아래는 random string 생성 예제인데, 좀더 fancy/tricky한 방법이 몇개 더 있는것 같지만 가장 직관적인 것 같다. (출처)
string gen_random(const int len) {
string r;
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) {
r += (char)(alphanum[rand() % (sizeof(alphanum) - 1)]);
}
return r;
}
string shuffle 예제. (출처)
string shuffle(string a) {
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(a.begin(), a.end(), default_random_engine(seed));
cout << "shuffle : " << a << endl;
return a;
}
아래는 random string 생성 예제인데, 좀더 fancy/tricky한 방법이 몇개 더 있는것 같지만 가장 직관적인 것 같다. (출처)
string gen_random(const int len) {
string r;
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) {
r += (char)(alphanum[rand() % (sizeof(alphanum) - 1)]);
}
return r;
}
2016년 2월 4일 목요일
네이버 내비게이션
네이버에서 내비게이션이 얼마전에 나왔다. 네이버에서 만든건 아니고 네이버 지도에 맵피 내비게이션을 붙였다고 하는데 정확한건 모르겠다. 아이폰은 없고 안드로이드에만 있다. 네이버에서 손을 댔으니 추후 아이폰도 지원하지 않을까 한다. 사용해보니 뭔가 아직 깔끔하게 정돈된 느낌은 아니고 이리저리 약간 지저분하기는 한데 사용하기에 불편함은 없다. 네이버 지도에서 검색 후 내비로 넘어갈 수도 있고, 내비에서 바로 검색도 가능하다.
무엇보다 검색능력이 타사 내비에 비해 압도적이어서 만족스럽다. 상호명이 약간 다르다거나 상호가 아니라 그냥 주소를 넣는다거나, 상호가 두 단어일 때 두 단어의 순서가 바뀐것, ‘강원도 편의점’처럼 지역과 추상어의 결합도 가능했다. 다른 내비게이션들도 되기는 되는데 매우 기능이 약해서 검색이 안되는 경우가 허다하다.
길안내 UI도 첫인상과는 달리 괜찮았다. 첫인상은 굉장히 허접해보이는데, 허접해 보이는 와중에도 보여야 할 정보가 보이지 않는다든지 하는 일은 없었다. 예전에 티맵을 쓰다가 티맵이 갈수록 자꾸 골목길로 안내를 한다든지 뻔한 길을 놔두고 돌아가는 길을 알려주는 일이 잦아져서 맵피, 올레내비, 현대자동차기본내비를 돌아가면서 썼다. 자동차 기본 내비는 자동차와의 일체감이 훌륭하고 예전처럼 구리지 않아서 충분히 그것만으로도 실사용이 가능하나 실시간 교통상황의 반영이 느리고, 올레내비는 너무 샛길로 빠지지도 않고 그렇다고 대로로만 가지도 않는, 정말 훌륭한 길을 알려주지만 UI가 너무 좋지 않아서 운전하면서 보기가 힘들다. 안내음성도 과속구간에서는 너무 시끄럽고, 빠지는 길에서는 어디에서 빠진다고 알려주는 타이밍이 타사 내비에 비해 좋지 않다. 지금 어디쯤 왔는지 보려고 해도 글씨가 너무 작아서 보기가 힘들다. 자동차 기본내비는 화면이 크다보니 이런점에는 절대적 우위에 있었다. 맵피는 이 둘의 균형이 아주 좋다. 길도 너무 어렵지 않으면서 적당히 빠른 길을 잘 알려주고 UI도 알아보기 좋고 음성안내도 적절하고. 나름 만족스러웠다. 다만, 균형이 좋다는건 어느것 하나 뛰어난 것이 없이 무난하다는 말도 되어서 ‘좋은 길’을 더욱 선호하는 나로서는 UI가 조금 불편해도 올레내비를 자주 사용하게 된다. (김기사는 그 어느것 하나 장점이랄만한 것이 없어서 두세번정도 사용해보고 곧바로 제외했다.)
네이버 내비는 위에 나열한 내비중에는 (당연하게도) 맵피에 가장 근접한데, 목표점 검색이 빠르고 정확해서 몇번 사용해보니 다른 내비가 너무 불편하게 느껴졌다. 위의 내비들은 공통적으로 동작이 느려서 ‘다들 그러니 원래 그런것이려니’하고 사용해왔는데 목표점 검색/설정/안내 - 이 세 동작이 빠르게 연결되는 내비를 써보니 다른점들은 다 고만고만하게 느껴진다. 앞으로는 네이버 내비를 주로 이용하게 될것 같다.
피드 구독하기:
글 (Atom)