2015-02-05 4 views
6

프랑스어 세큐리티 소셜 식별 번호는 두 자리 숫자로 끝납니다. 가능한 모든 가능한 common transcription error을 감지 할 수 있었으며 발견되지 않은 채 다른 종류의 오류 (예 :, 3 자리 연속)가 있음을 확인했습니다.OCaml에 상응하는 파이썬 생성기

def check_code(number): 
    return 97 - int(number) % 97 

def single_digit_generator(number): 
    for i in range(len(number)): 
     for wrong_digit in "": 
      yield number[:i] + wrong_digit + number[i+1:] 

def roll_generator(number): 
    for i in range(len(number) - 2): 
     yield number[:i] + number[i+2] + number[i] + number[i+1] + number[i+3:] 
     yield number[:i] + number[i+1] + number[i+2] + number[i] + number[i+3:] 

def find_error(generator, number): 
    control = check_code(number) 
    for wrong_number in generator(number): 
     if number != wrong_number and check_code(wrong_number) == control: 
      return (number, wrong_number) 

assert find_error(single_digit_generator, "0149517490979") is None 
assert find_error(roll_generator, "0149517490979") == ('0149517490979', '0149517499709') 

내 Python 2.7 코드 (위의 작업 조각)는 생성기를 많이 사용합니다. OCaml에서 어떻게 적용 할 수 있을지 궁금합니다. 확실하게 내부 상태를 유지하는 함수를 작성할 수는 있지만 순전히 기능적 솔루션을 찾고 있습니다. lazy 라이브러리를 공부해도 좋을까요? 나는 코드를 요구하지 않고 지시 만 받는다.

답변

4

: 여기

내 프로젝트 중 하나에서 촬영 한 예입니다

let range n = Stream.from (fun i -> if i < n then Some i else None);; 

for 구문 구조를 사용할 수는 없지만 Stream 모듈이 제공하는 일련의 함수를 사용하여 스트림의 상태를 확인하고 해당 요소를 반복합니다.

try 
    let r = range 10 in 
    while true do 
    Printf.printf "next element: %d\n" @@ Stream.next r 
    done 
with Stream.Failure ->();; 

이상 단순히 :

Stream.iter (Printf.printf "next element: %d\n") @@ range 10;; 

또한 camlp4 프리 프로세서가 제공하는 특수 구문 사용할 수 있습니다 :

Stream.iter (Printf.printf "next element: %d\n") [< '11; '3; '19; '52; '42 >];; 

다른 기능은 목록에서 스트림을 생성하는 문자열을 포함을 , 바이트 또는 심지어 채널. API documentation은 다른 가능성을 간결하게 설명합니다.

특수 구문의 앞 또는 뒤에 요소를 다시 넣어 수 있도록 당신이 그들을 구성 할 수 있지만, 처음에는 다소 직관적이지가 될 수 있습니다

let dump = Stream.iter (Printf.printf "next element: %d\n");; 

dump [< range 10; range 20 >];; 

첫 번째 스트림의 요소를 생성합니다 다음 선택 두 번째 스트림은 의 요소 바로 뒤에의 마지막 맺어진 요소의 순위로 정렬되므로이 경우 두 번째 스트림 만 반복되는 것처럼 나타납니다.

이 모든 요소를 ​​얻으려면, 당신은 'a Stream.t의 스트림을 구성하고 반복적으로 각 반복 수 :이 예상 출력을 생성 할

Stream.iter dump [< '(range 10); '(range 20) >];; 

.

OCaml (available online)에서 오래된 책을 읽고이 주제에 대한 더 나은 정보를 얻는 것이 좋습니다.

4

Core 라이브러리는 발전기를 파이썬 스타일로 제공합니다 (Sequence 모듈 참조). 언어의 확장을 사용하여, 당신은 단순히 스트림로 발전기를 정의 할 수 있습니다

open Core_kernel.Std 

let intersections tab (x : mem) : _ seq = 
    let open Sequence.Generator in 
    let init = return() in 
    let m = fold_intersections tab x ~init ~f:(fun addr x gen -> 
     gen >>= fun() -> yield (addr,x)) in 
    run m 
+0

어떤 링크가 있습니까? 이 ['Seq'] (http://batteries.forge.ocamlcore.org/doc.preview:batteries-beta1/html/api/Seq.html) 모듈에 대해 이야기합니까? – Aristide

+0

해당 모듈에 대한 링크를 추가했습니다. 'Seq'는'Sequence'에 대한 제 별명입니다. 이름을 다시 바꿨습니다. 제공된 링크에서 더 많은 예제를 찾을 수 있습니다. – ivg

+0

전체 Or_error 모듈 대신 Or_error.Monad_infix를 여는 것을 고려할 수도 있습니다. 일반적으로 더 적은 것보다는 더 적은 것을 여는 것이 더 낫습니다 ... – yzzlr