진화론 이야기 - 틱타알릭 화석 찾기

이미 오래전에, 고생물학자들은 그동안 발굴된 화석들을 토대로 생물들의 연대기와 진화경로를 그려놓았습니다. 그리고 아직 발견되지 않은 화석들은 어느 지층에서 어떤 모습을 하고 있으리라는 것을 예측했습니다. 그리고 그 이후 발견된 화석들은 모두 그 예측범위 안에 존재하고 있다는 것이 밝혀졌습니다.

이렇게 되자, 진화론자들은 예전처럼 무작정 화석을 찾아다니는 것이 아니라, 필요한 화석을 찾기 위해 발굴장소를 정할 수 있게 되었습니다.
틱타알릭 화석을 발견한 닐 슈빈(Neil Shubin) 교수도 마찬가지입니다. 그는 우연히 발견한 화석을 분석하여 네 발 달린 물고기란 것을 알아낸 것이 아닙니다. 처음부터 네 발 달린 물고기 화석을 찾기 위해 발굴장소를 고른 것입니다.

수백년 전부터 발굴된 화석들을 늘어놓은 결과, 양서류나 파충류로 보이는 화석들은 약 3억6500만년 전쯤 만들어진 암석에서 처음으로 나오기 시작합니다. 한편, 3억8500만년 전의 암석에서는 완전한 물고기들만이 나오고 있습니다.
그렇다면 슈빈교수의 목적인 '네 발 달린 물고기' 화석을 찾기 위해서는 나이가 3억8500만년~3억6500만년 사이인 지층 - 퇴적암 - 을 찾아야 한다는 결론이 나옵니다.

다음은 그러한 지층이 어디 있는지를 알아야 하는데, 이미 그러한 자료들은 여기저기 널려 있습니다. 정부나 석유회사 등에서 지질조사를 시행하고 그 결과를 공개했기 때문입니다.

약 3억7000만년 이전의, 고대에 개울이 흘렀던 흔적이 있는 장소로서 결정된 곳이 캐나다 북부의 섬지역입니다.그때부터 발굴단은 매년 여름마다 캐나다 북부에서 발굴작업을 시작하였습니다.
그리하여 2004년, 마침내 예측했던 대로 네 다리가 달린 물고기 화석을 발견할 수 있었습니다.



이렇게 화석증거는 아직 발견되지 않은 화석들의 위치와 모양을 예측할 수 있을 정도까지 체계가 잡혀 있습니다. 그러므로 창조론자들의 '화석증거가 진화론을 부정한다'는 말은 잘못입니다. 오히려 화석증거는 진화론을 지지해주는 수많은 기둥들 중 하나입니다.

출처 : 내 안의 물고기(닐 슈빈 저)

창조론 이야기 - 헥켈의 배아 사진

헥켈의 배아 사진 역시 창조론자가 우려먹는 사골(?) 중 하나입니다. 하도 많이 우려먹어 더이상 우러나올 것이 없을것 같은데도 잘도 우려먹고 있더군요.

헥켈이 배아사진을 조작한 것은 분명한 잘못입니다. 하지만 창조과학회의 전략(?) 때문인지, 헥켈의 배아 문제의 촛점은 사진위조에만 맞춰져 있을 뿐, 헥켈의 실험이 무엇을 의미하는지, 사진이 아닌 헥켈의 이론 자체가 맞는지 틀리는지는 별 관심을 갖지 않고 있습니다.

헥켈의 배아 실험의 의의는 '개체발생은 계통발생을 반복한다'는 것입니다. 실제로 인간의 배아를 관찰해 보면 아가미줄이 나타났다 사라지고, 꼬리가 나타났다 사라지는, 어류->포유류->인간으로의 계통발생을 반복하는 것을 알 수 있습니다.

창조론자들은 '사진조작'을 '실험조작'으로 확대해서 교과서에서 빼야 한다고 야단이더군요.
헥켈의 이론을 교과서에서 빼기는 아주 쉽습니다. 직접 실험을 통해 개체발생과 계통발생은 관련 없다는 것을 밝히는 것입니다. 그런데 창조론자들은 그런 실험을 하기보다는 헥켈의 위조에만 매달립니다. 실험을 통해서는 헥켈의 이론을 퇴출시킬 수 없기 - 즉 헥켈의 이론 자체는 틀리지 않기 - 때문이죠. 그러므로 헥켈이 조작했던 사진만 원래 사진으로 바꾸어 놓으면 헥켈의 이론 자체는 아무런 문제가 없습니다.

헥켈의 잘못이라면, 100점짜리 이론을 가지고 보너스를 더 받겠다고 사진을 조작했다는 것이죠. 그러나 결국 그 사실이 탄로나서 보너스는 커녕 오명만 뒤집어쓰고 말았습니다(물론 이것을 밝혀낸 것 역시 진화론자들이었지 창조론자가 아닙니다). 헥켈이 조작했던 사진만 되돌려놓는다면 100점짜리 이론 맞습니다. 그 때문에 헥켈의 이론은 교과서에서 퇴출당하지 않은 것입니다.

창조론 이야기 - 창조론자 눈의 필터

모든 창조론자들 눈에는 특정한 필터가 장착되어 있습니다. 마음에 들지 않는 부분은 가리는 필터죠.

어떤 진화론자가 이런 글을 씁니다.

진화론을 정확히 이해하기 위해서는 비교적 많은 지식이 필요하다. 유전학이나 고생물학 뿐 아니라 때로는 연대측정을 위한 핵물리학까지 알아야 한다. 이러한 지식이 없다면 진화론의 증거는 단지 근거없는 추측일 뿐이라고 생각할 수도 있다. 이것이 창조론자들이 진화의 증거는 없다고 주장하는 이유 중 하나다.


그런데 이 글도 창조론자들의 눈에는 다음과 같이 보입니다.

진화론을 정확히 이해하기 위해서는 비교적 많은 지식이 필요하다. 유전학이나 고생물학 뿐 아니라 때로는 연대측정을 위한 핵물리학까지 알아야 한다. 이러한 지식이 없다면 진화론의 증거는 단지 근거없는 추측일 뿐이라고 생각할 수도 있다. 이것이 창조론자들이 진화의 증거는 없다고 주장하는 이유 중 하나다.


그리하여 이 글은 진화론자들도 진화론의 허구성을 인정했다는 증거 - 유명한 진화론자도 '진화론의 증거는 단지 근거없는 추측일 뿐'이라고 했다 - 로서 편집되어 창조론자들 사이에 떠돌아다니게 됩니다.
이러한 예는 비교적 많이 보입니다. 심지어는 창조론자들 사이에서 '진화론 광신도'라 불리는 리처드 도킨스의 글을 다음과 같이 인용하더군요.

생물체의 구조를 살펴보면 누군가가 설계했다고 볼 수밖에 없는 그런 복잡성을 가지고 있다. 그러나 진화는 그러한 복잡성을 만들 수 있는 능력이 있다.


또는 어느 과학자가 이렇게 말합니다.

공룡이 새로 진화했다는 것이 정설이지만 사실 제 생각으로는 공룡이 새로 진화하지 않았습니다. 다만 이것은 아직까지 증거가 부족하기에 아직 연구중입니다.

이 글은 이렇게 보이게 됩니다.

공룡이 새로 진화했다는 것이 정설이지만 사실 제 생각으로는 공룡이 새로 진화하지 않았습니다. 다만 이것은 아직까지 증거가 부족하기에 아직 연구중입니다.

그래서 그의 말은 공룡의 진화를 거부한 과학자로서 소개될 것입니다.


이러한 필터는 창조론자면 누구나 가지고 있습니다. Time지 기사를 번역한 서울대 전산학과 고건교수도 마찬가지더군요.

The only certainty in this data-poor, imagination-rich, endlessly fascinating field is that there are plenty of surprises left to come.

진화론에 대한 기대를 표현한 원본이 그 필터를 통과하면 진화론 비하로 바뀌어버리는군요.(http://blog.naver.com/iiai/105451382)

그래서 저도 한가지 버릇이 생겼네요. 창조론자가 '진화론자도 이렇게 인정했다'고 하면 먼저 의심부터 하면서 원본을 요구하는 버릇 말입니다.

참고 : 마우스로 긁으면 창조론자들의 필터를 통과하지 않은 원본을 보실 수 있습니다.

창조론 이야기 - 필트다운인

창조론자들의 서적이나 블로그라면 빠지지 않는 것이 필트다운인입니다. 필트다운인의 보기를 들며 '진화론의 모든 증거는 조작이다'라고 주장하는 것이죠. 이를테면 여기 창조과학회처럼 말입니다(그림출처).

20세기 초까지 인류화석은 그다지 많이 발견되지 않았습니다. 일부 발견된 인류화석은 아시아나 유럽에서 주로 발견되었습니다.
자연히 인류의 발생지는 아시아 또는 유럽이라고 생각되었으며, 유럽의 많은 나라들이 '인류의 탄생지'라는 영예를 바라고 있었습니다.
이러한 경향은 영국에서도 마찬가지였고, 그런 영국에서 필트다운인이 발견되자 영국 과학계는 흥분해서 인류의 미싱링크로 선언하게 되었습니다. 그 후로 무려 20년간 필트다운인은 진화론의 정설로서 자리매김을 할 수 있었습니다.

그러나 20여년이 지나 더 많은 화석이 발견되면서 문제가 생기기 시작했습니다. 수많은 화석자료를 분석한 결과 아프리카에서 시작해서 전 세계로 뻗어나간 인류의 발자취를 추적할 수 있었지만, 그 속에서 필트다운인은 전혀 어울리지 않게 자리잡고 있었기 때문입니다.
결국 필트다운인에 대한 전면적인 재조사가 시작되었고, 마침내 필트다운인이 조작되었다는 사실이 발견된 것입니다.

과연 이것으로 창조론자들의 주장처럼 '진화론은 못믿을 것'이라는 결론이 나올 수 있을까요?

첫째, 진화론을 비롯한 과학이란 그 전체가 잘 짜여진 그물과 같은 것입니다. 과학 전체가 조작이 아닌 한, 조작은 티가 날 수밖에 없습니다. 위에서 보기를 든 것처럼 필트다운인 같은 조작된 증거는 그 이외의 증거들로부터 얻은 결과와 어울릴 수가 없습니다. 만약 창조론자들 주장처럼 진화론 전체가 조작이라고 한다면 진화론은 진화론 이외의 다른 과학 - 물리학, 천문학, 지질학 등과 충돌할 수밖에 없습니다(이 때문에 창조론자들은 진화론을 부정하기 위해 모든 과학 전체를 부정하곤 합니다).

둘째, 필트다운인 같은 경우는 무려 20년 이상이나 '정설'로서 취급되어 왔습니다. 그럼에도 불구하고 새로운 정보와 맞지 않는다는 것이 밝혀지자마자 재조사에 들어가 결국 조작임이 밝혀지고 말았죠. 이것은 과학의 '정화작용'이 제대로 작동한다는 증거입니다. 창조론자들의 생각과는 달리 이것은 진화론을 신뢰할 수 있다는 증거가 됩니다.

그러므로 창조론자들은 진화론을 깎아내리려 거짓말까지 해가며 애쓸 필요 없습니다. 만약 진화론이 정말로 잘못된 것이라면 과학의 자정작용에 의해 저절로 붕괴할 것입니다.
진화론자들도 진화론이 붕괴하는 것을 그다지 안타까와할 필요 없습니다. 진화론이 붕괴되고 새로이 만들어질 이론은 창조론이 아니라 진화론보다 더 '진실에 가까운 이론'이 될 테니까 말입니다.

-참고 : 직립보행(Craig Stanford)



뱀발 : 필트다운인에 관한 창조과학회 기사의 일부분을 발췌하겠습니다.

1. 속임수를 위한 준비 - 작업을 위한 시간과 생각.
2. 발견의 공표 - 잃어버린 고리가 발견되었다.
3. 항의들은 무시되었다 - 오늘날과 마찬가지로, 그것들에 대한 비판은 철저히 무시되었다.
4. 사기극임이 폭로되다 - 과학 탐정가들이 속임수를 밝혀냈다.

저 기사만을 보면, 진화론자들이 치밀하게 준비해서 증거를 조작한 후 '학계의 권위'를 이용해서 반론들을 무시하다가, 용감한 '과학탐정가(창조론자?)'에 의해 사기극임이 폭로된 것인줄 알겠습니다.
먼저 저 조작된 화석을 만든 것이 누군지는 밝혀지지 않았습니다. 범죄가 일어난지 20년이나 지나서 알게 되었으니까요. 심지어 용의자들 중에는 셜록홈즈의 작가 코난도일까지 거론되고 있는 상황입니다. '무죄추정의 원칙'에 있어서도 필트다운인을 진화론자가 조작했다는 주장은 말도 안됩니다.
또한, 위에서 말하는 '과학탐정가'들 속에 창조론자들은 없습니다. 속임수를 밝혀낸 것은 오히려 진화론자들입니다. 진화론의 잘못을 진화론자가 밝혀내서 진화론을 더욱 단단하게 만든 것입니다.
창조론자들은 그동안 아무것도 하지 않았습니다. 사실 필트다운인이 '정설' 대접을 받고 있는 동안에는 '진화론의 증거'인 필트다운인을 외면하고 있었습니다. 그러다가 진화론자들이 잘못을 고쳐 놓자, '옛날에 진화론자들이 잘못했었다'는 주장에만 매달리고 있는 것이죠.

GA - 오델로 - 결과

6. 결과
앞과 같은 방식으로 100세대 동안 진화시킨 결과입니다.
6개 무리에서 가장 적응도가 높은 개체들의 적응도 변화 그래프입니다.



서로간에 엎치락뒤치락하기는 합니다만, 이것만으로는 얼마나 실력이 좋아졌는지 알 수가 없습니다.
어쩔수 없이 기본이 되는 AI를 하나 만들어서 비교해야겠네요.
StandardAI라 이름붙인 이 AI는 오델로플레이어와 비슷하게 돌을 놓을 수 있는 장소들의 가중치를 계산합니다. 다만 가중치를 유전자에서 계산하는 것이 아니라, 그 위치에서 잡을 수 있는 돌의 수 * 그 위치의 중요도로 계산합니다. 그 위치의 중요도란 가장자리는 10, 가장자리에서 한칸 안쪽은 1, 나머지는 5로 정의합니다.

아무튼 매 세대마다 각 무리에서 최고가중치를 가진 오델로플레이어와 이 StandardAI를 10회 대결시킨 후 오델로플레이어가 얻은 점수를 그래프로 그린 결과는 다음과 같습니다.


여기서는 20세대도 채 지나기 전에 StandardAI를 상대로한 전과가 급상승하는 것을 알 수 있습니다. 참고로 이 때의 유전자 크기(즉 유전자가 가지고 있는 패턴 갯수)는 11039입니다(물론 이것이 최대값인지는 모릅니다. 세대가 진행되면서 더 늘어날 수도 있습니다).

7. 뱀발
결과적으로 유전자알고리즘이 얼마나 진화되었는지 알기 위해 StandardAI라는 새로운 AI를 만들 수밖에 없었습니다.
그렇다면, 구태여 공진화시킬 필요 없이 이 StandardAI와의 대결을 통해 적응도를 계산, 진화시킬 수도 있지 않을까요?
물론 그럴 수도 있습니다만, 만약 StandardAI와의 대결을 통해 진화시킨다면 한가지 큰 단점이 있습니다. 오델로플레이어들이 StandardAI만을 상대하기 위해 진화한다는 점이죠. 만약 StandardAI에게 어떤 약점이 존재한다면 그 약점만을 공략하는 오델로플레이어들이 진화할 가능성이 있습니다. 그렇게 된다면 StandardAI를 상대로는 강하지만 다른 AI(심지어는 StandardAI보다 약하지만 StandardAI의 약점이 없는 AI)들을 상대로는 맥을 못추는 오델로플레이어들이 진화될 수 있습니다.

GA - 오델로 - 경쟁 및 재생산

3. 경쟁
이제 유전자도 설계했으니 이들을 경쟁시켜서 적응도를 측정해야 합니다. 그런데 무엇과 경쟁시킬까요? 특정한 AI를 하나 만들어서 이 AI와 경쟁시켜야 할까요?
아, 전에도 종종 사용했던 공진화를 이용하면 구태여 AI를 따로 만들 필요가 없겠네요. 일이 줄었습니다.
여기서는 이 오델로플레이어들을 6개의 무리로 나누었습니다. 각 무리에는 512개씩의 오델로플레이어를 포함시켰습니다. 그리고는 이들 사이에서 경쟁을 시켰습니다.
각 오델로플레이어들은 같은 무리에 있는 것들과는 싸우지 않습니다. 다른 무리에 있는 것들과 싸우게 됩니다.

procedure Compatition()
.. for h := 0, 6 do
..... for p := 0, 512 do
........ Horde[h][p].Fitness := 0; // 모든 객체의 적응도 초기화
..... end
.. end

.. // 경쟁 시작
.. for white := 0, 6 do
..... for black := 0, 6 do
........ if white != black then
........... // Horde[white]와 Horde[black]간의 대결
........... // 랜덤한 상대를 만나기 위해
........... for k := 0, 512 do
.............. CardDeck[k] = k;
........... end
........... for k := 0, 512 do
.............. rnd := Random(0, 512);
.............. tmp = CardDeck[k];
.............. CardDeck[k] = CardDeck[rnd];
.............. CardDeck[rnd] = tmp;
........... end
........... for k := 0, 512 do
.............. Compatition(Horde[white][k], Horde[black][CardDeck[k]];
........... end
........ end
..... end
.. end
end

Compatition프로시저는 생략하겠습니다. 두 오델로플레이어끼리 대결을 시킨 후, 남아있는 자신의 돌 수를 Fitness에 더하는 프로시저입니다.

4. 재생산
이렇게 적응도를 구했으면 보다 많은 돌을 가진 오델로플레이어를 찾아 재생산을 시킵니다. 일단 재생산 대상은 T=0.99인 4차 토너먼트법 - 24 = 16개의 후보를 선택 후 토너먼트를 반복해서 하나 설정, 토너먼트의 승부는 1% 확률로 적응도 낮은 것이 승 - 으로 결정했습니다.

4.1 교차
다음과 같은 유전자를 가진 두 오델로플레이어가 선택되었다고 합시다.


'...+...', 0.327
'.MM.+EE.', 0.932
'EE+.M..', 0.142
'.MEEE+EE', 0.527
'EMMEE+EM', 0.106
'..EE+EEE', 0.172
'MME+MM..', 0.018
'..E+...', 0.437



'.MM.+EE.', 0.762
'..M+...', 0.007
'..EE+EEE', 0.120
'..M.+EE', 0.607
'E+EMME', 0.742
'EMMEE+EM', 0.224


검은색으로 표시된 유전자는 '가'와 '나'에 다 있지만, 붉은색으로 표시된 유전자는 '가'에만, 녹색 유전자는 '나'에만 존재하는 유전자입니다. 이를테면 '나'는 '..E+...'라는 패턴을 만난 적이 없습니다. 만약 '나'가 그 패턴을 만난다면 어떨까요? 규칙에 의해 이 패턴을 랜덤한 가중치와 함께 추가할 것입니다. 그러므로 지금 추가하더라도 상관 없겠죠.
교차를 하기 전에 '가'와 '나'는 서로가 가지고 있는 패턴을 공유합니다.



'...+...', 0.327
'.MM.+EE.', 0.932
'EE+.M..', 0.142
'.MEEE+EE', 0.527
'EMMEE+EM', 0.106
'..EE+EEE', 0.172
'MME+MM..', 0.018
'..E+...', 0.437
'..M+...', 0.725
'E+EMME', 0.176



'.MM.+EE.', 0.762
'..M+...', 0.007
'..EE+EEE', 0.120
'..M.+EE', 0.607
'E+EMME', 0.742
'EMMEE+EM', 0.224
'...+...', 0.301
'.MEEE+EE', 0.815
'MME+MM..', 0.328
'..E+...', 0.663


즉 '가'와 '나' 둘 다 10개의 동일한 패턴(가중치는 다르지만)을 가진 유전자가 되었습니다.
이후에는 '가'와 '나'에서 동일한 패턴을 꺼내서 50%확률로 가중치를 바꾸면 교차 완료입니다.

function FindPattern(gene, pattern) // gene에서 pattern과 동일한 것 찾음
.. for k := 0, gene.Size do
..... if IsSamePattern(gene.Pair[k].Pattern, pattern) then
........ return k; // 찾았으면 위치 리턴
..... end
.. end
.. return -1;
end

procedure CrossOver(childA, childB)
.. geneA = childA.Gene
.. geneB = childB.Gene
.. for locA := 0, geneA.Size do
..... locB := FindPattern(geneB, geneA.Pair[locA].Pattern
..... if locB == -1 then // 맞는 패턴이 없음, B에 추가
........ geneB.Pair[childB.Gene.Size].Pattern = geneA.Pair[locA].Pattern
........ geneB.Pair[childB.Gene.Size].Weight = Random(0, 1)
........
childB.Gene.Size + childB.Gene.Size + 1
..... end
.. end
.. // 생략 - 동일한 방법으로 B에만 있는 유전자 A에 추가

.. // 교차 시작
.. for locA := 0, geneA.Size do
..... locB := FindPattern(geneB, geneA.Pair[locA].Pattern
......... // 동일한 패턴을 B에서 찾음

..... if Random(0, 1)
0.5 then // 50%확률로 가중치 교환
........ tmp = geneA.Pair[locA].Weight
........
geneA.Pair[locA].Weight = geneB.Pair[locB].Weight
........
geneB.Pair[locB].Weight = tmp
..... end
.. end
end


4.2 돌연변이
돌연변이는 비교적 간단합니다. 오델로플레이어의 모든 유전자를 돌면서 일정확률로 가중치값을 변화시키면 됩니다.

procedure Mutantation(child)
.. for k := 0, child.Gene.Size do
..... if Random(0, 1)
< 0.001 then
........
child.Gene.Pair[k].Weight = Random(0, 1)
..... end
.. end
end

5. 이주
앞에서 설명한 것처럼, 오델로플레이어들을 공진화시키기 위해 고립된 6개의 무리를 만들어 그 안에서만 번식이 일어나도록 하였습니다. 특히 512개밖에 안되는 무리 안에서만 번식시킨다면 아무리 돌연변이를 적용시키더라도 유전자가 획일화되기 쉽습니다. 그러므로 이렇게 유전적으로 고립시킨 경우에는 가끔씩 일부 개체들을 이주시켜 새로운 유전자를 섞어주는 것이 좋습니다.

procedure Migration()
.. if Generation % 10 == 9 then // 10세대에 한번씩
..... do
........ a := Random(0, 6)
........ b := Random(0, 6)
..... while a == b

..... aa := Random(0, 512)
..... bb := Random(0, 512)
..... tmp = horde[a][aa];
..... horde[a][aa] = horde[b][bb];
..... horde[b][bb] = tmp;
end

GA - 오델로 - 유전자 작업 프로시저들

2. 유전자 초기화 및 각종 작업 프로시저
앞에서 이야기한 것처럼 오델로플레이어가 기존에 마주치지 못했던 패턴을 만난다면 그 패턴을 추가합니다. 그러므로 초기화는 유전자묶음을 비우는 것으로 할 수 있습니다.

procedure GeneInitialize(gene)
.. gene.Size := 0;
end

그리고, 현 상황에서 만든 패턴을 가지고 가중치를 가져오기 위한 프로시저(함수)입니다.

fuction WeightOfPattern(gene, pattern)
.. for k := 0, gene.Size do
..... // gene.Pair[k]는 패턴과 가중치의 쌍
..... if IsSamePattern(gene.Pair[k].Pattern, pattern) then
........ // 패턴이 일치할 경우
........ return gene.Pair[k].Weight;
..... end
.. end
.. // 같은 패턴을 찾지 못했을 경우 패턴추가
.. //
gene.Size위치에 추가
.. rndweight :=
Random(0, 1) // 0~1 사이의 랜덤값
.. gene.Pair[gene.Size].Pattern := pattern;
.. gene.Pair[
gene.Size].Weight := rndweight;
.. gene.Size := gene.Size + 1;
.. return rndweight;
end

즉 패턴을 찾았으면 해당패턴의 가중치를, 찾지 못했으면 임의의 가중치로 추가한 후 가중치를 리턴합니다.
이 함수에서 사용한 IsSamePattern은 다음과 같이 방향을 무시하고 비교하는 함수입니다.

function IsSamePattern(patternA, patternB)
.. lenA := patternA.PatternLength;
.. lenB := patternB.PatternLength;
.. if lenA != lenB then // 길이가 다를 경우
..... return false;
.. end
.. for k := 0, lenA do
..... if patternA[k] !=patternB[k] then // 다를 경우
........ break; // for루프 빠져나감
..... end
.. end
.. if k == lenA then // 루프를 다 돌았음 - 일치
..... return true;
.. end
.. for k := 0, lenA do
..... if patternA[k] != patternB[lenB - k - 1] then // 역순으로 비교, 다를경우
........ return false
..... end
.. end
.. return true; // 비교완료, 동일함
end