Monday, February 29, 2016

Project Euler #26 Reciprocal cycles

For this particular problem, you are supposed to find the longest repeating decimal from rational number where 1 is divided by certain integer n.
As always you could try with brute force method to detect repeating patterns, however, you will find difficulties with so called mixed repeating decimals.
For example 1/6 is 0.166666.... so if you trying to queue numbers, and try to match pattern, you might face some issues given the fact that prefix before repeating pattern is not determined.

So instead, I decided to queue remainders each step after. You will get more idea instead of reading this wordy explanation. See implementation below in both Java and C.
One more thing, to optimize a little bit, I assumed that fact that repeating decimal of non-prime is shorter than repeating decimal of prime number. I will omit proof of this idea.
C:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int get_answer(int N);
int generate_data(int N);

int DATA[10001];
int LIST[10001];

int main()
{
    int T, N;
    generate_data(10000);
    cin >> T;
    while (T--) {
        cin >> N;
        cout << get_answer(N) << endl;
    }
    return 0;
}

int get_answer(int N)
{
    int MAX = -1;
    int index = 1;
    for (int i = 3; i < N; i++) {
        if (DATA[i] > MAX) {
            MAX = DATA[i];
            index = i;
        }
    }
    return index;
}

int is_prime(int N)
{
    int i;
    if(N%2 == 0) return 1;
    if(N%3 == 0) return 1;
    for (i=3;i<=sqrt(N);i+=2) {
        if(N%i == 0)  return 0;
    }
    return 1;
}


int generate_data(int N)
{
    double n;    
    int q, index, count, flag;
    int max = -1, max_index = 0;
    for (int i = 3; i <= N; i++) {
        n = 1;
        flag = 0;
        count = 0;
        if (i % 5 == 0 || i % 2 == 0) {
            DATA[i] = 0;
            continue;
        }
        if (i > 5 && !is_prime(i)) {
            // cout << i << " is prime." << endl;
            DATA[i] = 0;
            continue;
        }
        index = 0;
        while (true) {
            while (n < i) {
                n *= 10;
            }
            n = fmod(n, (double) i);
            if (n == 0) {
                index = 0;
                break;
            }
            int count2;
            if (count > 10) {
                count2 = 10;
            } else {
                count2 = count;
            }
            for (int j = 0; j < count2; j++) {
                if (LIST[j] == n) {
                    flag = 1;
                    break;
                }
            }
            if (flag) {
                break;
            }
            LIST[count++] = n;
        }
        DATA[i] = count - index;
        if (DATA[i] > max) {
            max = DATA[i];
            max_index = i;
        }
    }
    return max_index;
}
Java:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public class Solution {

    private static HashMap<Integer, Integer> DATA = new HashMap<Integer, Integer>();

    public static void main(String[] args) {
        int T, N;
        Scanner sc = new Scanner(System.in);
        generateData();
        T = sc.nextInt();
        while (T-- > 0) {
            N = sc.nextInt();
            System.out.println(getAnswer(N));
        }
        sc.close();
    }

    private static void generateData() {
        int n, q, index;
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (int i = 3; i <= 10000; i++) {
            n = 1;
            if (i % 5 == 0) {
                DATA.put(i, 0);
                continue;
            }
            index = 0;
            while (true) {
                while (n < i) {
                    n *= 10;
                }
                n %= i;
                // System.out.println("i:" + i + " n:" + n);
                if (n == 0) {
                    index = 0;
                    break;
                }
                if (list.contains(n)) {
                    index = list.indexOf(n);
                    break;
                }
                list.add(n);
            }
            DATA.put(i, list.size() - index);
            list.clear();
        }
    }

    private static int getAnswer(int N) {
        int MAX = Integer.MIN_VALUE;
        int index = 1;
        for (int i = 3; i <= N; i++) {
            if (DATA.get(i) != null && DATA.get(i) > MAX) {
                MAX = DATA.get(i);
                index = i;
            }
        }
        return index;
    }
}

Friday, February 19, 2016

Project Euler #24 Lexicographic permutation

Generally speaking permutation algorithm requires n! space and time to enumerate all possible permutations. When it comes to permute given strings in lexicographic order there is better algorithm as follows.
Cite from Wikipedia (https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order)
1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
2. Find the largest index l greater than k such that a[k] < a[l].
3. Swap the value of a[k] with that of a[l].
4. Reverse the sequence from a[k + 1] up to and including the final element a[n].

And here is my implementation in Java:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Scanner;

public class Solution {

    private static final String ORIGINAL = "abcdefghijklm";
    private static ArrayList<String> LISTS = new ArrayList<String>();
    private static int count = 0;
    private static int count2 = 0;
    private static long T;
    private static long N;
    private static ArrayList<Long> NS = new ArrayList<Long>();
    private static ArrayList<Long> NS_SORTED = new ArrayList<Long>();
    private static int cnt = 0;
    private static HashMap<Long, String> ANSWERS = new HashMap<Long, String>();

    public static void main(String[] arg) {
        Scanner sc = new Scanner(System.in);
        T = sc.nextInt();
        for (int i = 0; i < T; i++) {
            N = sc.nextLong();
            NS.add(N);
            NS_SORTED.add(N);
        }
        Collections.sort(NS_SORTED);
        N = NS_SORTED.get(NS_SORTED.size() - 1);
        permute_better(ORIGINAL.toCharArray());
        // System.out.println(NS);
        // System.out.println(NS_SORTED);
        // System.out.println(N);
        // System.out.println(ANSWERS);
        for (int i = 0; i < T; i++) {
            System.out.println(ANSWERS.get(NS.get(i)));
        }
        sc.close();
    }

    public static void permute_bruteforce(char[] ca, int l, int r) {
        int i;
        if (l == r) {
            // LISTS.add(new String(ca));
            count++;
        } else {
            for (i = l; i <= r; i++) {
                char c = ca[l];
                ca[l] = ca[i];
                ca[i] = c;
                permute_bruteforce(ca, l + 1, r);
                char d = ca[l];
                ca[l] = ca[i];
                ca[i] = d;
            }
        }
    }

    // 1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the
    // permutation is the last permutation.
    // 2. Find the largest index l greater than k such that a[k] < a[l].
    // 3. Swap the value of a[k] with that of a[l].
    // 4. Reverse the sequence from a[k + 1] up to and including the final element a[n].

    public static void permute_better(char[] ca) {
        boolean isKChanged = true;
        int k, l;
        char c;
        while (isKChanged && count2 < N) {
            isKChanged = false;
            k = 0;
            // System.out.println("CNT:" + NS_SORTED.get(cnt));
            if (count2 == NS_SORTED.get(cnt) - 1) {
                ANSWERS.put(NS_SORTED.get(cnt), new String(ca));
                cnt++;
            }
            for (int i = ca.length - 2; i >= 0; i--) {
                if (ca[i] < ca[i + 1]) {
                    isKChanged = true;
                    k = i;
                    break;
                }
            }
            // System.out.println("k=" + k);
            l = ca.length - 1;
            for (int i = ca.length - 1; i >= 0; i--) {
                if (ca[i] > ca[k]) {
                    l = i;
                    break;
                }
            }
            // System.out.println("l=" + l);
            // System.out.println("Swap " + ca[k] + " and " + ca[l]);
            c = ca[k];
            ca[k] = ca[l];
            ca[l] = c;
            int start = k + 1;
            int last = ca.length - 1;
            while (start <= last) {
                // System.out.println("Swap " + ca[start] + " and " + ca[last]);
                c = ca[start];
                ca[start] = ca[last];
                ca[last] = c;
                start++;
                last--;
            }
            // System.out.println(ca);
            count2++;
        }
    }

}

Found this awesome solution from projecteuler.net:
[b]ssavi[/b] said
[quote]My C++ Code 
[code=C/C++]
#include<bits/stdc++.h>
#define LL long long

using namespace std;

LL arr[15];

void fff()
{
    arr[0] = 1;
    for(int i=1; i<=13; i++)
        arr[i] = arr[i-1] * i;
}

LL cool(LL m, LL temp)
{
    //cout<<m<<' '<<temp<<endl;
    LL c;
    for(LL i=1; i<=13; i++)
    {
        if(m*i>=temp) { c = i - 1; break;}
    }
    return c;
}

int main()
{
    fff();
    string str, temp = "";
    LL n, to, test;
    scanf("%lld", &test);
    while(test--)
    {
        scanf("%lld", &n);
        str = "abcdefghijklm";
        temp ="";
        to = n;
        for(LL i=1; i<=13; i++)
        {
            LL id = cool(arr[13-i], to);
            to = to - (arr[13-i]*id);
            temp = temp + str[id];
            str.erase(id,1);
        }
        cout<<temp<<endl;
    }
    return 0;
}

Amazon AWS

Play with Amazon AWS, EMR.

Reload

I admit that I ditched this blog for roughly 2 years. That does not mean I was totally out of field. From now on, this blog will disclose my personal notes for mainly two thing; Machine Learning and general programming topics. For machine learning, I'd like to grasp my understanding of Stanford's UFLDL as well as Google's Tensorflow. When it comes to general programming topics, I will simply enumerate ideas and concepts.