Computus in scala and java
In the spirit of the holiday, I figured I would try my hand at writing computus in scala and java. For those who aren't aware, computus is the algorithm used to compute which day easter falls on.
First, the scala version:
and now the java version
I realize the scala implementation is basically "java in scala", but an interesting data point is that the the scala version is about 20% slower. From my perspective, it seems like the scala version should have almost identical performance characteristics to the java version.
More importantly, I must certainly be doing doing something wrong. Iterating and building the list in this manner cannot be the "right" way to do this, but I'm drawing a blank at how to improve things. Aside from the performance characteristics, I'm really interested in trying to improve the scala version to make it more idiomatic. I'm pretty sure I'm hampered by my lack of experience with functional languages.
First, the scala version:
object Computus { def main(args: Array[String]) { val start = System.currentTimeMillis() for (year <- 2000.until(1000000)) { println(pretty_computus(year)) } println(System.currentTimeMillis()-start) } def golden(year:Long):Long = { year % 19 + 1 } def century(year:Long):Long = { (year / 100) +1 } def solar(year:Long):Long = { (3 * (century(year) /4) ) -12 } def lunar(year:Long):Long = { ((8 * century(year) +5) / 25) - 5 } def letter(year:Long):Long = { 5 * year / 4 - solar(year) - 10 } def epact(year:Long):Long = { (11 * golden(year) + 20 +lunar(year) - solar(year)) %30 } def correct_9006(year:Long):Long = { val epact_val = epact(year) if (epact_val < 0) { epact_val + 30 } else { epact_val } } def correct_epact(year:Long):Long = { val epact_val = correct_9006(year) if (((epact_val ==25) && (golden(year) > 11)) || (epact_val ==24)) { epact_val + 1 } else { epact_val } } def n_whatever(year:Long):Long = { 44- correct_epact(year) } def fix_n(year:Long):Long = { val n=n_whatever(year) if (n<21){ n + 30 } else { n } } def computus(year:Long):Long = { fix_n(year) + 7 -((letter(year)+fix_n(year))%7) } def pretty_computus(year:Long):String = { val day_of_march = computus(year) if (day_of_march>31) { "April " + (day_of_march -31).toString() } else { "March " + day_of_march.toString() } } }
and now the java version
public class JavaComputus { public static void main(String[] args) { Long start = System.currentTimeMillis(); for (long i = 2000; i < 1000000; i++) { System.out.println(pretty_computus(i)); } System.out.println(System.currentTimeMillis()-start); } public static Long golden(Long year) { return year % 19 + 1; } public static Long century(Long year) { return (year / 100) +1; } public static Long solar(Long year) { return (3 * (century(year) /4) ) -12; } public static Long lunar(Long year) { return ((8 * century(year) +5) / 25) - 5; } public static Long letter(Long year) { return 5 * year / 4 - solar(year) - 10; } public static Long epact(Long year) { return (11 * golden(year) + 20 +lunar(year) - solar(year)) %30; } public static Long correct_9006(Long year) { Long epact_val = epact(year); if (epact_val < 0) { return epact_val + 30; } else { return epact_val; } } public static Long correct_epact(Long year) { Long epact_val = correct_9006(year); if (((epact_val ==25) && (golden(year) > 11)) || (epact_val ==24)) { return epact_val + 1; } else { return epact_val; } } public static Long n_whatever(Long year) { return 44- correct_epact(year); } public static Long fix_n(Long year) { Long n=n_whatever(year); if (n<21){ return n + 30; } else { return n; } } public static Long computus(Long year) { return fix_n(year) + 7 -((letter(year)+fix_n(year))%7); } public static String pretty_computus(Long year) { Long day_of_march = computus(year); if (day_of_march>31) { return "April " + ((Long)(day_of_march -31)).toString(); } else { return "March " + day_of_march.toString(); } } }
I realize the scala implementation is basically "java in scala", but an interesting data point is that the the scala version is about 20% slower. From my perspective, it seems like the scala version should have almost identical performance characteristics to the java version.
More importantly, I must certainly be doing doing something wrong. Iterating and building the list in this manner cannot be the "right" way to do this, but I'm drawing a blank at how to improve things. Aside from the performance characteristics, I'm really interested in trying to improve the scala version to make it more idiomatic. I'm pretty sure I'm hampered by my lack of experience with functional languages.
Comments