Project Euler #74: Digit factorial chains

Sort by

recency

|

12 Discussions

|

  • + 0 comments

    C++

    #include <bits/stdc++.h>
    #define prev Prev
    using namespace std;
    
    vector<int> factorial = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
    unordered_set<int> bad = {720, 5043, 151, 122, 5, 120, 4, 24, 26, 722, 5044, 169, 363601, 145, 1454, 40585, 871, 178, 278};
    
    set<vector<int>> bad_digits;
    
    int MAX = 1000000;
    int N, L;
    
    vector<set<int>> M(61);
    vector<int> chainLength(1000010, -1);
    
    map<vector<int>, int> permutation;
    
    vector<int> GetDigits(int num)
    {
        vector<int> digits;
        
        while(num)
        {
            digits.push_back(num % 10);
            num /= 10;
        }
        sort(digits.begin(), digits.end());
        return digits;
    }
    
    int GetSum(int num)
    {
        int sum = 0;
        
        while(num)
        {
            sum += factorial[num % 10];
            num /= 10;
        }
        return sum;
    }
    
    void Search()
    {
        M[2] = {0};    
      
        for(int i = 1; i <= MAX; i++)
        {                
            int length = 1;
            int num = i;
            
            set<int> found = {num};        
            vector<int> digits = GetDigits(num);
                            
            if(!bad.count(GetSum(i)) && !bad_digits.count(digits) && permutation.count(digits))
            {
                M[chainLength[permutation[digits]]].insert(i);
                continue;
            }
                            
            while(length < 60)
            {        
                int sum = (num == 0) ? 1 : GetSum(num);                                                
                                        
                if(found.count(sum)) 
                {
                    num = sum;
                    break;
                }
                found.insert(sum);            
                length++;
                num = sum;
            }        
            chainLength[i] = length;
            M[length].insert(i);
            permutation[digits] = i;
        }    
    }
    int main() 
    {    
        for(auto it : bad)
        {
            bad_digits.insert(GetDigits(it));
            bad.insert(GetSum(it));
        }    
        int t;    
        cin >> t;
        
        Search();    
        
        while(t--)
        {
            cin >> N >> L;
            
            if(M[L].empty() || *M[L].begin() > N) 
            {
                cout << -1 << "\n";
                continue;
            }
            
            for(auto it : M[L]) 
            {
                if(it > N) break;
                cout << it << ' ';
            }
            cout << "\n";
        }
        return 0;
    }
    
  • + 0 comments

    java

    public class Solution {

    public static void main(String[] args) {
        // factorial of digits from 1 to 9
        int [] fact = {1,1,2,6,24,120,720,5040,40320,362880};
    
        ArrayList<ArrayList<Integer>> arr = new ArrayList<ArrayList<Integer>>();
    
        for(int i=0;i<=60;i++) arr.add(new ArrayList<Integer>());
    
        for(int i = 0;i<=1000000;i++){
    
            // to check i has loop as defined in problem statement 
            HashSet<Long> h = new HashSet<Long>();
            long fsum = i;
            String s = ""+i;
            int len = 0;
            while(h.contains(fsum) == false){
                h.add(fsum);
                fsum = 0;
                len++;
                if(len>60) break;
                // to cal sum of factorial of digits
                for(int j = 0;j<s.length();j++) fsum += fact[s.charAt(j)-'0'];
                s = ""+fsum;
            } 
            if(len<=60)
               arr.get(len-1).add(i);
        }
        // output according to test case
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while(t-- != 0){
            int num = sc.nextInt(),l = sc.nextInt();
            int c = 0;
            for(Integer i: arr.get(l-1)){
                if(i<=num) {
                    System.out.print(i + " ");
                    c++;
                }
                else break;
            }
            if(c == 0) System.out.print(-1);
            System.out.println();
        }
    
    }
    

    }

  • + 0 comments
    #!/bin/python3
    
    import sys
    import math
    import time
    
    
    
    def fac(n):
        res = 0
        for num in str(n):
            res += FACTORIAL10[int(num)]
        return res
    
    FACTORIAL10 = [math.factorial(i) for i in range(10)]
    
    mem = {}
    def get_chain(n):
        chain = []
        while True:
            chain.append(n)
            if n in mem:
                n = mem[n]
            else:
                i = fac(n)
                mem[n] = i
                n = i
            if n in chain:
                break
        return chain
    
    # circular chains up to 10^6
    circular_chains = {
        #[145, 145]
        145: 1,
        #[169, 363601, 1454, 169]
        169: 3,
        #[871, 45361, 871]
        871: 2,
        #[872, 45362, 872]
        872: 2,
        #[1454, 169, 363601, 1454]
        1454: 3,
        #[40585, 40585]
        40585: 1,
        #[45361, 871, 45361]
        45361: 2,
        #[45362, 872, 45362]
        45362: 2,
        #[363601, 1454, 169, 363601]
        363601: 3,
    }
    
    inputs = [tuple(map(int, input().strip().split())) for _ in range(int(input().strip()))]
    
    st = time.time()
    
    seen = {}
    for N, L in inputs:
        res = []
        for i in range(N + 1):
            chain = 0
            if i in circular_chains:
                chain = circular_chains[i]
            else:
                s = "".join(sorted(str(i)))
                chain = seen[s] if s in seen else len(get_chain(i))
                seen[s] = chain
            if chain == L:
                res.append(i)
        if len(res) > 0:
            print(" ".join(map(str, res)))
        else:
            print(-1)
    
    print(f"Time: {time.time() - st} secs")
    
  • + 0 comments

    Don't forget to sort your result in ascending order or you will fail all testcases

  • + 0 comments

    Check value of this number in your code for correct ANSWERS:
    0 -> 2
    1 -> 1
    2 -> 1
    145 -> 1
    169 -> 3
    871 -> 2
    872 -> 2
    1454 -> 3
    40585 -> 1
    45361 -> 2
    45362 -> 2
    363601 -> 3