Friday, April 19, 2013

How to Solve Mayan Long Count Problem

Problem Description:
The Mayan Long Count calendar is a counting of days with these units: "* The Maya name for a day was k'in. Twenty of these k'ins are known as a winal or uinal. Eighteen winals make one tun. Twenty tuns are known as a k'atun. Twenty k'atuns make a b'ak'tun.*". Essentially, we have this pattern:
  • 1 kin = 1 day
  • 1 uinal = 20 kin
  • 1 tun = 18 uinal
  • 1 katun = 20 tun
  • 1 baktun = 20 katun
  • The long count date format follows the number of each type, from longest-to-shortest time measurement, separated by dots. As an example, '12.17.16.7.5' means 12 baktun, 17 katun, 16 tun, 7 uinal, and 5 kin. This is also the date that corresponds to January 1st, 1970. Another example would be December 21st, 2012: '13.0.0.0.0'. This date is completely valid, though shown here as an example of a "roll-over" date.

    Write a function that accepts a year, month, and day and returns the Mayan Long Count corresponding to that date. You must remember to take into account leap-year logic, but only have to convert dates after the 1st of January, 1970.

    Input Description:
    Through standard console, expect an integer N, then a new-line, followed by N lines which have three integers each: a day, month, and year. These integers are guaranteed to be valid days and either on or after the 1st of Jan. 1970.

    Output Description:
    For each given line, output a new line in the long-form Mayan calendar format: <Baktun>.<Katun>.<Tun>.<Uinal>.<Kin>.

    Sample Input:

    3
    1 1 1970
    20 7 1988
    12 12 2012
    
    Sample Output:
    12.17.16.7.5
    12.18.15.4.0
    12.19.19.17.11
    
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.Scanner;
    
    public class MayanLongCount {
        private static class MayanCalendar {
            private final int kin;
            private final int uinal;
            private final int tun;
            private final int katun;
            private final int baktun;
            
            public MayanCalendar(int baktun, int katun, int tun, int uinal, int kin) {
                this.baktun = baktun;
                this.katun = katun;
                this.tun = tun;
                this.uinal = uinal;
                this.kin = kin;
            }
            
            @Override
            public String toString() {
                return baktun + "." + katun + "." + tun + "." + uinal + "." + kin;
            }
        }
        
        private static Date epochTime() {
            Calendar cal = Calendar.getInstance();
            cal.setTime(new Date(0));
            return cal.getTime();
        }
        
        private static long getNumberOfDays(Date date1, Date date2) {
            return ((date2.getTime() - date1.getTime()) / (1000 * 60 * 60 * 24));
        }
        
        private static MayanCalendar toMayanCalendar(long numberOfDays) {
            long numOfMayanDaysBeforeEpoch = 0;
            int[] mayanEpoch = new int[]{12, 17, 16, 7, 5};
            int[] mayan = new int[]{20*20*18*20, 20*18*20, 18*20, 20, 1};
            for (int i = 0; i < mayan.length; i++) {
                numOfMayanDaysBeforeEpoch += mayan[i] * mayanEpoch[i];
            }
            int[] result = new int[mayan.length];
            long remainder = numberOfDays + numOfMayanDaysBeforeEpoch;
            for (int i = 0; i < mayan.length; i++) {
                int value = (int) (remainder / mayan[i]);
                if (value > 0) {
                    remainder = remainder % mayan[i];
                }
                result[i] = value;
            }
            return new MayanCalendar(
                result[0], result[1], result[2], result[3], result[4]);
        }
        
        public static void main(String[] args) throws Exception {
            Scanner scanner = null;
            try {
                scanner = new Scanner(System.in);
                int n = Integer.parseInt(scanner.nextLine());
                for (int i = 0; i < n; i++) {
                    Date epoch = epochTime();
                    Date input = new SimpleDateFormat("dd MM yyyy")
                        .parse(scanner.nextLine());
                    long numberOfDays = getNumberOfDays(epoch, input);
                    MayanCalendar mc = toMayanCalendar(numberOfDays);
                    System.out.println(mc);
                }
            } finally {
                scanner.close();
            }
        }
    }
    

    Tuesday, April 16, 2013

    Creating a Simple Calendar Application in SWT

    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.events.MouseAdapter;
    import org.eclipse.swt.events.MouseEvent;
    import org.eclipse.swt.graphics.Color;
    import org.eclipse.swt.layout.GridData;
    import org.eclipse.swt.layout.GridLayout;
    import org.eclipse.swt.widgets.Button;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Label;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.swt.widgets.Table;
    import org.eclipse.swt.widgets.TableColumn;
    import org.eclipse.swt.widgets.TableItem;
    
    public class JCalendar {
        private static Calendar currentTime = Calendar.getInstance();
        private static Label dateLabel;
        private static Table table;
        
        private static void updateDate(Calendar calendar) {
            dateLabel.setText(new SimpleDateFormat("MMM YYYY").format(calendar.getTime()));
        }
        
        private static void createNavigation(final Shell shell, final Calendar calendar) {
            Composite composite = new Composite(shell, SWT.BORDER);
            composite.setLayout(new GridLayout(3, true));
            composite.setLayoutData(
                new GridData(GridData.FILL, GridData.FILL, true, true));
            
            Button leftArrowButton = new Button(composite, SWT.PUSH);
            leftArrowButton.setText("<");
            leftArrowButton.setLayoutData(
                new GridData(GridData.FILL, GridData.FILL, true, true));
            leftArrowButton.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseDown(MouseEvent e) {
                    calendar.add(Calendar.MONTH, -1);
                    updateDate(calendar);
                    updateCalendar(shell, table, calendar);
                    shell.pack();
                }
            });
            
            dateLabel = new Label(composite, SWT.CENTER);
            dateLabel.setLayoutData(
                new GridData(GridData.FILL, GridData.FILL, true, true));
            updateDate(calendar);
            
            Button rightArrowButton = new Button(composite, SWT.PUSH);
            rightArrowButton.setText(">");
            rightArrowButton.setLayoutData(
                new GridData(GridData.FILL, GridData.FILL, true, true));
            rightArrowButton.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseDown(MouseEvent e) {
                    calendar.add(Calendar.MONTH, 1);
                    updateDate(calendar);
                    updateCalendar(shell, table, calendar);
                    shell.pack();
                }
            });
        }
        
        private static void addRows(Shell shell, Calendar calendar) {
            int currentDayOfMonth = currentTime.get(Calendar.DAY_OF_MONTH);
            int currentYear = currentTime.get(Calendar.YEAR);
            int currentMonth = currentTime.get(Calendar.MONDAY);
            
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
            int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH);
            
            TableItem item = new TableItem(table, SWT.NONE);
            for (int i = 0; i < dayOfWeek-1; i++) {
                item.setText(i, "  ");
            }
            int value = 1;
            for (int i = 0; i < 7-dayOfWeek+1; i++) {
                String day = Integer.toString(value);
                if (value < 10) {
                    day = " " + value;
                }
                item.setText(i+dayOfWeek-1, day);
                value++;
            }
            
            while (value <= daysInMonth) {
                item = new TableItem(table, SWT.NONE);
                for (int j = 0; j < 7; j++) {
                    if (value <= daysInMonth) {
                        if (value == currentDayOfMonth
                            && currentYear == year && currentMonth == month) {
                            Color blue = new Color(shell.getDisplay(), 0, 0, 255);
                            item.setForeground(j, blue);
                            blue.dispose();
                        }
                        String day = Integer.toString(value);
                        if (value < 10) {
                            day = " " + value;
                        }
                        item.setText(j, day);
                    } else {
                        item.setText(j, "  ");
                    }
                    value++;
                }
            }
        }
        
        private static void updateCalendar(Shell shell, Table table, Calendar calendar) {
            table.removeAll();
            addRows(shell, calendar);
        }
        
        private static void createCalendar(Shell shell, Calendar calendar) {
            table = new Table(shell, SWT.BORDER);
            table.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
            table.setLinesVisible(true);
            table.setHeaderVisible(true);
    
            String[] titles = {
                "S", "M", "T", "W", "T", "F", "S"
            };
            for (int i = 0; i < titles.length; i++) {
                TableColumn column = new TableColumn(table, SWT.NONE);
                column.setResizable(false);
                column.setText(titles[i]);
            }
            
            addRows(shell, calendar);
            
            for (int i = 0; i < titles.length; i++) {
                table.getColumn(i).pack();
            }
        }
        
        public static void main(String[] args) {
            
            Display display = new Display();
            Shell shell = new Shell(display,
                SWT.TITLE | SWT.CLOSE | SWT.BORDER & (~SWT.RESIZE));
            shell.setText("Calendar");
            shell.setLayout(new GridLayout());
            
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(currentTime.getTime());
            createNavigation(shell, calendar);
            createCalendar(shell, calendar);
            
            shell.pack();
            shell.open();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
            display.dispose();
        }
    }
    

    Monday, April 15, 2013

    How to Implement Digital Root

    Below is an implementation of Digital Root in Go.
    package main
    
    import (
        "fmt"
        "os"
        "strconv"
    )
    
    func digitalRoot(n int) int {
        if n < 10 {
            return n
        }
        sum := 0
        for n > 0 {
            sum += n % 10
            n /= 10
        }
        return digitalRoot(sum)
    }
    
    func main() {
        n, e := strconv.Atoi(os.Args[1])
        if e != nil {
            fmt.Println("Invalid number:", os.Args[1])
            os.Exit(1)
        }
        fmt.Println(digitalRoot(n))
    }
    

    Thursday, April 11, 2013

    How to Implement Powerset

    Below is a simple implementation of Powerset in Go.
    package main
    
    import (
        "fmt"
        "sort"
        "strings"
    )
    
    func powerset(set []int) [][]int {
        m := map[string][]int{}
        m = recursePowerset(set, m)
        result := [][]int{set}
        for _, v := range m {
            result = append(result, v)
        }
        return result
    }
    
    func join(s []int) string {
        result := []string{}
        for _, v := range s {
            result = append(result, string(v))
        }
        return strings.Join(result, ",")
    }
    
    func recursePowerset(set []int, accumulator map[string][]int) map[string][]int {
        if len(set) == 0 {
            return accumulator
        }
        for i, _ := range set {
            subset := make([]int, len(set[:i]))
            copy(subset, set[:i])
            subset = append(subset, set[i+1:len(set)]...)
            sort.Ints(subset)
            key := join(subset)
            accumulator[key] = subset
            accumulator = recursePowerset(subset, accumulator)
        }
        return accumulator
    }
    
    func main() {
        set := []int{1, 2, 3, 4}
        powset := powerset(set)
        // pretty print the output
        for i := 0; i <= len(set); i++ {
            for _, v := range powset {
                if len(v) == i {
                    fmt.Println(v)
                }
            }
        }
    }
    
    Output:
    []
    [1]
    [4]
    [2]
    [3]
    [1 2]
    [2 4]
    [1 4]
    [3 4]
    [1 3]
    [2 3]
    [1 3 4]
    [2 3 4]
    [1 2 4]
    [1 2 3]
    [1 2 3 4]
    

    Monday, April 8, 2013

    How to Publish Artifacts with Gradle

    In this blog, I'm going to show you how to publish and consume artifacts with Gradle using both Ivy and Maven plugins.

  • Publishing via Ivy (old way)
  • apply plugin: "java"
    
    group = "test"
    version = "0.0.1"
    
    repositories {
        mavenCentral()
    }
    
    uploadArchives {
        repositories {
            ivy {
                url "file://home/foo/tmp/ivy"
            }
        }
    }
    
    dependencies {
        // just an example to test transitive dependencies
        compile "ch.qos.logback:logback-classic:1.0.11"
        compile "ch.qos.logback:logback-core:1.0.11"
    }
    
  • Publishing via Ivy (new way)
  • apply plugin: "java"
    apply plugin: "ivy-publish"
    
    group = "test"
    version = "0.0.1"
    
    repositories {
        mavenCentral()
    }
    
    publishing {
        publications {
            ivyJava(IvyPublication) {
                from components.java
            }
        }
        repositories {
            ivy {
                url "file://home/foo/tmp/ivy"
            }
        }
    }
    
    dependencies {
        // just an example to test transitive dependencies
        compile "ch.qos.logback:logback-classic:1.0.11"
        compile "ch.qos.logback:logback-core:1.0.11"
    }
    
  • Publishing via Maven (old way)
  • apply plugin: "java"
    apply plugin: "maven"
    
    group = "test"
    version = "0.0.1"
    
    repositories {
        mavenCentral()
    }
    
    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file:///home/foo/tmp/maven")
            }
        }
    }
    
    dependencies {
        // just an example to test transitive dependencies
        compile "ch.qos.logback:logback-classic:1.0.11"
        compile "ch.qos.logback:logback-core:1.0.11"
    }
    
  • Publishing via Maven (new way)
  • apply plugin: "java"
    apply plugin: "maven-publish"
    
    group = "test"
    version = "0.0.1"
    
    repositories {
        mavenCentral()
    }
    
    publishing {
        publications {
            mavenJava(MavenPublication) {
                from components.java
            }
       }
        repositories {
            maven {
                url "file://home/foo/tmp/maven"
            }
        }
    }
    
    dependencies {
        // just an example to test transitive dependencies
        compile "ch.qos.logback:logback-classic:1.0.11"
        compile "ch.qos.logback:logback-core:1.0.11"
    }
    
  • Consuming via Ivy
  • apply plugin: "java"
    
    version = "0.0.1"
    
    repositories {
        mavenCentral()
        ivy { url "file://home/foo/tmp/ivy" }
    }
    
    dependencies {
        compile "test:upload-artifact:0.0.1"
    }
    
  • Consuming via Maven
  • apply plugin: "java"
    
    version = "0.0.1"
    
    repositories {
        mavenCentral()
        maven { url "file://home/foo/tmp/maven" }
    }
    
    dependencies {
        compile "test:upload-artifact:0.0.1"
    }
    

    Tuesday, April 2, 2013

    How to Implement Pascal's Triangle

    My simple implementation of Pascal's Triangle in Go.
    package main
    
    import "fmt"
    import "os"
    import "strconv"
    
    func pascal(n int) [][]int {
        result := make([][]int, n)
        // initial value
        idx := 0
        result[idx] = []int{1}
        return recursePascal(idx, n, result)
    }
    
    func recursePascal(idx int, length int, accumulator [][]int) [][]int {
        if (idx == length-1) {
            return accumulator
        }
        slice := []int{1}
        for i := 0; i < len(accumulator[idx])-1; i++ {
            slice = append(slice,
                accumulator[idx][i] + accumulator[idx][i+1])
        }
        slice = append(slice, 1)
        idx++
        accumulator[idx] = slice
        return recursePascal(idx, length, accumulator)
    }
    
    func main() {
        n, _ := strconv.Atoi(os.Args[1])
        for _, v := range pascal(n) {
            fmt.Println(v)
        }
    }