作者: Tsutomu Hiroshima
日時: 2002/6/24(08:19)
廣島です.
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!!