Google Foobar 挑战 2 级 "Hey-I-Already-Did-That"

Google Foobar Challenge Level 2 "Hey-I-Already-Did-That"

我需要帮助解决 Google 的 Foobar 挑战的第二关。


指挥官 Lambda 使用自动算法随机分配小兵任务,以让她的小兵保持警惕。但是您已经注意到该算法中的一个缺陷 - 它最终会自行循环,因此它不会在迭代时分配新的 minions,而是陷入价值循环,因此相同的 minions 最终会反复执行相同的任务再次。您认为向指挥官 Lambda 证明这一点将有助于您为下一次晋升做准备。

你算出算法有以下过程:

1) 从一个随机的minion ID n开始,它是一个基数b
中长度为k的非负整数 2) 将 x 和 y 定义为长度为 k 的整数。 x有n的数字降序排列,y有n的数字升序排列
3) 定义 z = x - y。如有必要,将前导零添加到 z 以保持长度 k
4) 赋值n = z得到下一个minion ID,回到步骤2

例如,给定 minion ID n = 1211,k = 4,b = 10,则 x = 2111,y = 1112 和 z = 2111 - 1112 = 0999。那么下一个 minion ID 将是 n = 0999然后算法再次迭代:x = 9990、y = 0999 和 z = 9990 - 0999 = 8991,依此类推。

根据 n、k(从 n 派生)和 b 的值,算法在某个点达到循环,例如达到恒定值。例如,从n = 210022, k = 6, b = 3开始,算法会到达值的循环[210111, 122221, 102212],无论继续迭代多少次,都会停留在这个循环中。从n = 1211开始,例程将达到整数6174,并且由于7641 - 1467是6174,因此无论迭代多少次都将保持该值。

给定一个 minion ID 作为字符串 n,表示基数 b 中长度为 k 的非负整数,其中 2 <= k <= 9 且 2 <= b <= 10,编写函数 solution(n, b)其中returns是上述算法的结束循环长度,从n开始。例如,在上面的示例中,solution(210022, 3) 将 return 3,因为在 102212 上迭代将 return 到 210111,当以 3 为基数完成时。如果算法达到常数,例如 0 ,则长度为1.

测试用例:
Solution.solution("1211", 10) returns 1
Solution.solution("210022", 3) returns 3

这是我的代码:

import java.util.ArrayList;
import java.util.Arrays;

public class Solution {

    public static int solution(String n, int b) {
        int k = n.length();
        String m = n;
        ArrayList<String> minionID = new ArrayList<>();

        while (!minionID.contains(m)) {
            minionID.add(m);
            char[] s = m.toCharArray();
            Arrays.sort(s);
            int y = Integer.parseInt(toString(s));
            int x = Integer.parseInt(reverseString(s));
            if (b == 10) {
                int intM = x - y;
                m = Integer.toString(intM);
            } else {
                int intM10 = ((int) Integer.parseInt(toBase10(x,b))) - ((int) Integer.parseInt(toBase10(y, b)));
                m = toBaseN(intM10, b);
            }

            m = addLeadingZeros(k, m);
        }
        System.out.println(minionID);
        return minionID.size() - minionID.indexOf(m);
    }

    private static String toBaseN (int intBase10, int b) {
        int residual = intBase10;
        ArrayList<String> digitsBaseN = new ArrayList<>();

        while (residual >= b) {
            int r = residual % b;
            digitsBaseN.add(Integer.toString(residual));
            residual = (residual - r) / b;
        }
        digitsBaseN.add(Integer.toString(residual));

        StringBuilder reverseDigits = new StringBuilder();
        for (int i = digitsBaseN.size() -1; i >= 0; i--) {
            reverseDigits.append(digitsBaseN.get(i));
        }
        return reverseDigits.toString();
    }

    private static String toBase10 (int intBaseN, int b) {
        int[] xArr = new int[Integer.toString(intBaseN).length()];
        int count = 0;
        for (int i = xArr.length - 1; i >= 0; i--) {
            xArr[count] = Integer.toString(intBaseN).charAt(i) - '0';
            count++;
        }

        int yBase10 = 0;

        for(int i = 0; i < xArr.length; i++) {
            yBase10 += xArr[i] * (Math.pow(b, i));
        }
        return Integer.toString(yBase10);
    }

    public static String toString(char[] arr) {
        StringBuilder newString = new StringBuilder();
        for (char c : arr) {
            newString.append(c);
        }
        if (newString.toString().contains("-")) {
            newString.deleteCharAt(0);
        }
        return newString.toString();
    }

    public static String reverseString(char[] arr) {
        StringBuilder newString = new StringBuilder();
        for (int i = arr.length - 1; i >= 0; i--) {
            newString.append(arr[i]);
        }
        if (newString.toString().contains("-")) {
            newString.deleteCharAt(newString.length()-1);
        }
        return newString.toString();
    }

    public static String addLeadingZeros(int k, String z) {
        if (k > z.length()) {
            String zeros = "";
            for (int i = 0; i < (k - z.length()); i++) {
                zeros += "0";
            }
            zeros += z;
            return zeros;
        }
        return z;
    }

它只适用于十个测试用例中的三个

def answer(n, b):

    k = len(n)
    m = n
    mini_id = []
    while m not in mini_id:
        mini_id.append(m)
        s = sorted(m)
        x_descend = ''.join(s[::-1])
        y_ascend = ''.join(s)        
        if b == 10:
            int_m = int(x_descend) - int(y_ascend)
            m = str(int_m)
        else:
            int_m_10 = int(to_base_10(x_descend, b)) - int(to_base_10(y_ascend, b))
            m = to_base_n(str(int_m_10), b)

        m =  (k - len(m)) * '0' + m
    return len(mini_id) - mini_id.index(m)