廣島です.
Deutshland を応援しながら,
もっと簡潔なアルゴリズムがあることに気づきました.
と,言うか,全く初歩的なミスを犯していたのでした.
P[n] = 1 + r + ... + r^n から,
P[n+1] = 1 + r + ... + r^n + r^(n+1) を求めるのに,
P[n+1] = P[n] + r^(n+1) としていたのです.
もちろん正解は,
P[n+1] = 1 + r * P[n]
ああ,情けない.
以下,Scheme, Common Lisp, Ruby, Perl(Math::BigInt)版です.
全て,x を受け取り,x * b = 111...111 となる b と
111...111 の桁数 c のリストまたは配列を返します.
不正な引数の場合,各言語で偽にあたるオブジェクトを返します.
;; Scheme 版(改)
(define (f x)
(and (integer? x)
(positive? x)
(odd? x)
(not (zero? (remainder x 5)))
(let loop ((a (remainder 1 x)) (b (quotient 1 x)) (c 1))
(if (zero? a)
(list b c)
(let ((s (+ (* a 10) 1)))
(loop (remainder s x) (+ (* b 10) (quotient s x)) (+ c 1)))))))
;; Common Lisp 版(新)
(defun f (x)
(and (integerp x)
(plusp x)
(oddp x)
(not (zerop (rem x 5)))
(do* ((s 0 (+ (* a 10) 1))
(a (rem 1 x) (rem s x))
(b (truncate (/ 1 x)) (+ (* b 10) (truncate (/ s x))))
(c 1 (+ c 1)))
((zerop a) (list b c)))))
## Ruby 版(改)
def f(x)
return false unless x.is_a?(Integer) && x > 0 && x & 1 != 0 && x % 5 != 0
a = 1 % x; b = 1 / x; c = 1
while a.nonzero? do
s = a * 10 + 1
a = s % x
b = b * 10 + s / x
c += 1
end
return [b, c]
end
## Perl 版(改)
## Math::BigInt の使い方も少し分かって来ました.
use Math::BigInt;
sub f {
my $x = shift;
return unless $x =~ /^\d*[1379]$/;
my ($a, $b, $c, $s) = (1 % $x, int(1 / $x), 1);
while ($a) {
$s = $a * 10 + 1;
$a = $s % $x;
$b = Math::BigInt::badd(Math::BigInt::bmul($b, 10), int($s / $x));
$c ++;
}
$b =~ s/^\+//;
return ($b, $c);
}
-----------------------------
廣島 勉
(tsutomu@...)
Toi, Toi, Toi, Deutschland!!