Problem 55 "Lychrel numbers"

If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.

Not all numbers produce palindromes so quickly. For example,

349 + 943 = 1292,
1292 + 2921 = 4213
4213 + 3124 = 7337

That is, 349 took three iterations to arrive at a palindrome.

Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).

Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994.

How many Lychrel numbers are there below ten-thousand?

NOTE: Wording was modified slightly on 24 April 2007 to emphasise the theoretical nature of Lychrel numbers.

問 55 「Lychrel数」

47とその反転を足し合わせると, 47 + 74 = 121となり, 回文数になる.

全ての数が素早く回文数になるわけではない. 349を考えよう,

  • 349 + 943 = 1292
  • 1292 + 2921 = 4213
  • 4213 + 3124 = 7337

349は, 3回の操作を経て回文数になる.

まだ証明はされていないが, 196のようないくつかの数字は回文数にならないと考えられている.

反転したものを足すという操作を経ても回文数にならないものをLychrel数と呼ぶ.

先のような数の理論的な性質により, またこの問題の目的のために, Lychrel数で無いと証明されていない数はLychrel数だと仮定する.

更に, 10000未満の数については,常に以下のどちらか一方が成り立つと仮定してよい.

  1. 50回未満の操作で回文数になる
  2. まだ誰も回文数まで到達していない

実際, 10677が50回以上の操作を必要とする最初の数である: 4668731596684224866951378664 (53回の操作で28桁のこの回文数になる).

驚くべきことに, 回文数かつLychrel数であるものが存在する. 最初の数は4994である.

10000未満のLychrel数の個数を答えよ.

fn merge_each_other(num: &mut Vec<u8>, rev: &mut Vec<u8>) {
    let mut carry = 0u8;
    rev.iter().zip(num.iter_mut()).for_each(|(&r, d)| {
        let s = r + *d + carry;
        *d = s % 10;
        carry = s / 10;
    });
    if carry != 0 {
        num.push(carry);
        rev.push(0);
    }
    num.iter()
        .rev()
        .zip(rev.iter_mut())
        .for_each(|(&d, r)| *r = d);
}

fn symmetric_digit_vector_pair(mut n: u32, num: &mut Vec<u8>, rev: &mut Vec<u8>) {
    num.clear();
    rev.clear();
    while n > 0 {
        let d = (n % 10) as u8;
        rev.push(d);
        n /= 10;
    }
    rev.iter().rev().for_each(|&d| num.push(d));
}

fn main() {
    let mut count = 0u32;
    let mut num = Vec::with_capacity(56);
    let mut rev = Vec::with_capacity(56);
    'next_num: for n in 10u32..10_000 {
        symmetric_digit_vector_pair(n, &mut num, &mut rev);
        for _ in 0..50 {
            merge_each_other(&mut num, &mut rev);
            if rev == num {
                continue 'next_num;
            }
        }
        count += 1;
    }

    println!("{}", count);
    assert_eq!(count, 249);
}

use std::collections::LinkedList;

fn merge_each_other(num: &mut LinkedList<u8>, rev: &mut LinkedList<u8>) {
    let mut carry = 0u8;
    rev.iter().zip(num.iter_mut()).for_each(|(&r, d)| {
        let s = r + *d + carry;
        *d = s % 10;
        carry = s / 10;
    });
    if carry != 0 {
        num.push_back(carry);
        rev.push_back(0);
    }
    num.iter()
        .rev()
        .zip(rev.iter_mut())
        .for_each(|(&d, r)| *r = d);
}

fn symmetric_digit_vector_pair(mut n: u32) -> (LinkedList<u8>, LinkedList<u8>) {
    let mut rev = LinkedList::new();
    while n > 0 {
        let d = (n % 10) as u8;
        rev.push_back(d);
        n /= 10;
    }
    let num = rev.iter().rev().map(|&d| d).collect::<LinkedList<u8>>();
    (num, rev)
}

fn main() {
    let mut count = 0u32;
    'next_num: for n in 10u32..10_000 {
        let (mut num, mut rev) = symmetric_digit_vector_pair(n);
        for _ in 0..50 {
            merge_each_other(&mut num, &mut rev);
            if rev == num {
                continue 'next_num;
            }
        }
        count += 1;
    }

    println!("{}", count);
    assert_eq!(count, 249);
}