참여해주신 분들께 다시 한 번 감사드리며, 늦은 포스팅에도 기다려주셔서 감사드립니다. 모두가 도전을 완료할 수 있었습니다. JMP 직원이 아닌 직원을 대상으로 추가된 가장 큰 숫자(~200만 자릿수)와 가장 큰 1,000자리 목록(~2,000개 항목) 챌린지 모두 다음이 이겼습니다. @David_Burnham . 직원 항목의 경우 5초 이내에 추가된 가장 큰 두 숫자는 약 2,200만( @brady_brady 그리고 @Craige_Hales ) 그리고 가장 큰 목록은 약 61,500개 요소였습니다( 과제 3 예제 3.JSL ). 이 스크립트는 아래에 게시되었습니다.
세 가지 챌린지의 총 포인트는 다음과 같습니다.
두 숫자를 포함하는 연산부터 시작해 보겠습니다. 과제 3 예 1 – Slow.JSL 대부분의 항목과 유사한 구현을 제공합니다.
- 숫자가 같은(더하기) 또는 반대(뺄셈) 기호인지 확인합니다.
- 숫자 문자열을 구문 분석합니다.
- 덧셈/뺄셈 연산을 수행합니다.
- 결과를 연결하여 답변을 작성합니다.
덧셈과 뺄셈 연산이 단일 함수에서 수행되는지 아니면 여러 함수에서 수행되는지는 스타일의 문제이며 프로그램 명확성과 가독성에만 영향을 미치고 실행 시간에는 영향을 미치지 않습니다. 그러나 큰 차이를 만드는 것은 입력 숫자를 구문 분석하고 다시 합치는 방법입니다. 개별 숫자를 반복하기 전에 입력 문자열을 구문 분석합니다( 도전과제 3 예시 1 – 더 빨라졌습니다.JSL ) 루프 내부가 아닌 약 5배(2.28초 대 2개의 16,000자리 숫자를 추가하는 데 0.464초)의 작업 속도를 높입니다. 결과를 목록으로 수집한 다음 마지막 항목을 연결하여 루프 내부에서 개별 문자열 연결을 제거하면 작업 속도가 10배(0.04054초) 이상 빨라집니다. (챌린지 3 예 1 – 가장 빠른.JSL)을 참조하세요.
이를 더욱 빠르게 만드는 방법에 대해 이야기하기 전에 목록에 숫자를 추가하는 방법에 대해 이야기해야 합니다. 거의 모든 사람이 한 번에 한 항목씩 목록을 반복하고 각 항목을 누적 합계에 추가하여 이 문제를 처리했습니다. 이것이 궁극적으로 가장 빠른 접근 방식은 아니었지만 예외적으로 빠르게 만들 수 있었습니다( 도전 3 - Hales.JSL 5초 안에 1000자리 숫자 51,000개 추가). 대부분의 작업과 마찬가지로 속도 향상의 핵심은 작업 수를 최소화하는 것입니다. 제공된 예에서는 과제 3 예제 2.JSL , 해결책은 각 숫자 쌍에 대한 한 세트의 캐리/빌딩 작업을 총 3개의 세트로 줄이는 것이었습니다. 이는 다음을 통해 수행되었습니다.
- 입력 숫자를 두 개의 행렬로 로드합니다. 하나는 양수이고 다른 하나는 음수입니다.
- 다음을 사용하여 각 행렬을 개별적으로 추가합니다. V 합계 , 두 결과 행렬에 대해 한 세트의 캐리 연산을 수행합니다.
- 큰 수에서 작은 수를 뺍니다. 결과에 대해 일련의 차용 작업을 한 번 수행합니다. 최종 뺄셈은 위에서 설명한 두 숫자 알고리즘을 사용하여 수행됩니다.
두 자리 숫자와 목록 작업은 모두 캐리/대여 작업 중에 한 번에 두 자리 이상을 고려하여 더 빠르게 수행할 수 있습니다. 이 작업은 두 곳 모두에서 이루어졌습니다. 도전과제 3 - Hales.JSL 그리고 도전과제 3 - Brady.JSL . 자연스러운 성향은 하나의 숫자를 더하기/빼기/나르기/빌리는 것이지만, 오버플로가 발생하지 않는다면 약간의 독창성을 사용하여 절차를 가능한 한 많은 숫자로 일반화할 수 있습니다. ~ 안에 JMP , 숫자가 두 개인 경우에는 14자리이고 14 – 바닥(로그10( 목록크기 - 1)) 숫자 , 어디 목록크기 목록의 경우 입력 목록의 항목 수입니다. 왜 그런지 이해하려면 약 9e16에 오버플로가 발생한다는 점을 기억하세요. 가장 큰 2개의 15자리 숫자(9 15)를 추가하면 오버플로 오류가 발생합니다. 두 개의 가장 큰 14자리 숫자를 더하는 것은 그렇지 않습니다. 마찬가지로 9,999,999,999,999를 자신에게 추가하면 11~100회(정확히는 91회) 수행될 때 오버플로가 발생합니다.
이것이 어떻게 작동하는지에 대한 예로, 각 숫자가 14개의 레지스터에 배열된 세 개의 숫자를 추가하는 것을 고려해 보십시오.
11 99999999999999
22 99999999999999
33 99999999999999
첫 번째 레지스터(14 9s)의 값을 합산하면 다음과 같습니다.
2 99999999999997
2를 가지고 두 번째 레지스터를 합산하면 다음과 같습니다.
68
마지막 숫자는
68 99999999999997
이 접근 방식의 적용은 다음과 같습니다. 과제 3 예제 3.JSL . 200만 자리 숫자 2개를 더하는 평균 처리 시간은 4.7초에서 0.82초로 5배 이상 빨라졌습니다. 추가 조정으로 속도가 2배 더 향상될 수 있습니다. 도전과제 3 - Hales.JSL 그리고 도전과제 3 - Brady.JSL 1000자리 숫자 10,000개를 추가하는 데 필요한 시간이 4.5초에서 0.88초(5X)로 단축되었습니다. 이는 가장 빠른 목록 추가 접근 방식을 제공합니다.
2020년 7월 20일: 이번에는 또 하나의 버그 수정이 이루어졌습니다. 과제 3 예제 3.JSL . 세 가지 예제 1 파일 모두에 행렬 인수를 사용할 때 경고 메시지가 추가되었습니다(예제 2까지 구현되지 않음).
2020년 7월 17일: Challenge 3 예제 1 스크립트에서 또 다른 버그를 발견했으며 세 가지 모두 수정되고 교체되었습니다.
2020년 7월 16일 : 스크립트를 교체했습니다 과제 3 예 1 - Slow.JSL 그리고 과제 3 예 1 - 더 빨라졌습니다.JSL 끝에 문제를 일으키는 줄이 포함되어 있기 때문입니다(코드를 테스트하는 데 사용했던 테이블을 참조합니다). 이러한 파일을 다운로드했지만 문제를 직접 해결하지 못한 경우 이전 복사본을 교체하세요.