回文積
30分プログラム、その262。回文積 via Project Euler。
左右どちらから読んでも同じ値になる数を回文数という。 2桁の数の積で表される回文数のうち、最大のものは 9009 = 91 * 99 である。
では、3桁の数の積で表される回文数のうち最大のものはいくらになるか。
ちょうど読み終わったガウディ本(asin:4798113468)にも回文積が載っていた。曰く、「制約プログラミングを使えば、6桁の回文積を0.2秒でリストアップできるぜい、500MHzのCPUで」だそうです。制約プログラミングは非決定性計算に近いけれど、すべての条件を利用して枝刈りをするので速いらしい。あと、もうちょっと高速なCPUを使ってもいいと思います。
制約プログラミングはそもそも利用法が分からないので、非決定性計算でごまかす。Gaucheでamb、誰か実装してないかなーと探したら、id:Gemmaさんのコードがでてきた。
使い方
$gosh kaibun.scm (888 737)
ソースコード
#! /opt/local/bin/gosh ;; -*- mode:scheme; coding:utf-8 -*- ;; ;; kaibun.scm - ;; ;; Copyright(C) 2008 by mzp ;; Author: MIZUNO Hiroki / mzpppp at gmail dot com ;; http://howdyworld.org ;; ;; Timestamp: 2008/03/14 21:44:45 ;; ;; This program is free software; you can redistribute it and/or ;; modify it under MIT Lincence. ;; ;; http://practical-scheme.net/wiliki/wiliki.cgi?Scheme%3A%E6%95%B0%E9%81%8A%E3%81%B3 (use srfi-1) ;; stack of cc. (define fail '()) ;; nondeterminsm operator (define (amb li) (if (null? li) ((pop! fail)) (call/cc (lambda (cc) (push! fail (lambda () (cc (amb (cdr li))))) (car li))))) ;;; kaibun num (define (digit) (amb (reverse (iota 9)))) (define (digits) (+ (* 100 (digit)) (* 10 (digit)) (digit))) (define (palindrome) (letrec ((a (digits)) (b (digits)) (x (* a b))) (if (and (>= a 100) (>= b 100) (eq? (modulo (quotient x 100000) 10) (modulo (quotient x 1) 10)) (eq? (modulo (quotient x 10000) 10) (modulo (quotient x 10) 10)) (eq? (modulo (quotient x 1000) 10) (modulo (quotient x 100) 10))) (list a b) (amb '())))) (define (main _) (print (call/cc (lambda(cc) (push! fail (lambda () (cc 'no-choice))) (palindrome)))))