Thursday, 27 October 2016

Implement pagination with Spring-data-jpa framework

Today I have learnt a new way of dealing with pagination using Spring-data-jpa framework

 <dependency>  
   <groupId>org.springframework.data</groupId>  
   <artifactId>spring-data-jpa</artifactId>  
   <version>1.10.4.RELEASE</version>  
 </dependency>  

In the repository class

 @Query("Select E from Employee E where E.age >=:age")  
 public Page<Employee> findByAge(@Param("age")int age, Pageable pageable);  

Usage example. Pretty straight forward.

 Page<Employee> page = employeeRepo.findByAge(18, new PageRequest(0, 1, Direction.DESC, "age"));  
 if (page.getNumberOfElements() > 0){  
      return page.getContent().get(0);  
 }  
 return null;  

Thursday, 22 September 2016

Spring MVC + jQuery Ajax get post cheat sheet

Get


 $.get( "get", { name: "John", time: "2pm" }, function( data ) {  
      alert( "Data Loaded: " + data );  
 });  

 @RequestMapping(value = "/get", method = RequestMethod.GET)  
 @ResponseBody  
 public String get(@RequestParam String name, @RequestParam time) throws Exception{  
      return "Hello "+name+" "+time;  
 }  

Post

 $.post("post", { name: "John", time: "2pm"}, function(data) {  
      alert( "Data Loaded: " + data );  
 });  

There are two ways to handle the request in controller
1. Use Request parameter
2. Use ModelAttributes

 //1st way  
 @RequestMapping(value = "/post", method = RequestMethod.POST)  
 @ResponseBody  
 public String post(@RequestParam String name, @RequestParam time) throws Exception{  
      return "Hello "+name+" "+time;  
 }  
 
 //2nd way
 public class AjaxRequest {  
      private String name;  
      private String time;  
      //Ingore setters and getters  
 }  
     
 @RequestMapping(value = "/post", method = RequestMethod.POST)  
 @ResponseBody  
 public String post(@ModelAttribute AjaxRequest request) throws Exception{  
      return "Hello "+name+" "+time;  
 }  

What if you want to use @RequestBody?

You cannot use the shorthand form $.post any more. You must use $.ajax method and specify the contentType as 'application/json' and stringify the data using JSON.stringify()

 $.ajax({  
      type : "POST",  
      //must set the contentType for @RequestBody annotation to work, otherwise use @ModelAttribute to replace @RequestBody  
      contentType : "application/json",   
      url : "post",  
      //must use the stringify method to convert to json format  
      data : JSON.stringify({ name: "John", time: "2pm"}),  
      success : function(data) {  
           console.log("SUCCESS: ", data);  
      }  
 });  
   
 @RequestMapping(value = "/post", method = RequestMethod.POST)  
 @ResponseBody  
 public String post(@RequestBody AjaxRequest request) throws Exception{  
      return "Hello "+name+" "+time;  
 }  

JSTL < c:url >

<c:url value='/abc' /> = context root name + "/abc"

In jsp
Context root name = ${pageContext.request.contextPath} (e.g. myApp)

Note c:url doesn't do URL encoding -- it doesn't convert 'a b' to 'a%20b'

Neither HttpServletResponse.encodeURL(Strin url) nor HttpServletResponse.encodeRedirectURL(String url) encodes URL

URLEncoder.encode(String url) does the job

http://www.cnblogs.com/season-huang/p/3439277.html
https://bluxte.net/musings/2006/03/29/servletpath-and-pathinfo-servlet-api-weirdness/

Monday, 29 August 2016

Project Euler Problem 26: Reciprocal cycles

Problem


A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
1/20.5
1/30.(3)
1/40.25
1/50.2
1/60.1(6)
1/70.(142857)
1/80.125
1/90.(1)
1/100.1
Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.
Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

Solution

Use array to store the index of occurred digits is very efficient. Take 7 as example, each mod is 1,3,2,6,4,5, they are saved as arr[1]=1, arr[3]=2, arr[2]=3, arr[6]=4, arr[4]=5, arr[5]=6. Once you find an arr[i] such that arr[i] != 0, you immediately know the length.


      private static final int LIMIT = 1000;  
      public static void main(String[] args) {  
           int result = 0;  
           int longest = 0;  
           for (int i=2; i<LIMIT; i++){  
                int recurringNum = recurringNum(i);   
                if (recurringNum > longest){  
                     longest = recurringNum;  
                     result = i;  
                }  
           }  
           System.out.println(result);  
      }  
      public static int recurringNum(int num) {  
           int[] arr = new int[num+1];  
           int index = 1;  
           int mod = 1;  
           while(mod != 0 && arr[mod] == 0){  
                arr[mod]=index++;  
                mod = mod * 10 % num;  
           }  
           if (mod == 0){  
                return 0;  
           }  
           return index-arr[mod];  
   }  

Sunday, 28 August 2016

Project Euler Problem 23: Non-abundant sums

Problem

A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.

A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.

As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.

Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.

Solution

Initially I was using a Set to store all the abundant sum number. The performance was OK. But once I changed Set to List, the performance degraded badly. It prompted me to change the use of collection to a boolean array. I am pretty happy about the performance gain. 

      private static final int LIMIT = 28123;  
      private static final List<Integer> abundant = new ArrayList<>();  
      private static final boolean[] isAbundantSum = new boolean[LIMIT+1];  
      public static void main(String[] args) {  
           for (int i=1; i<=LIMIT; i++){  
                if (isAbundant(i)){  
                     abundant.add(i);  
                     for (int j : abundant){  
                          if (i+j <= LIMIT){  
                               isAbundantSum[i+j] = true;  
                          }  
                     }  
                }  
           }  
           int sum = 0;  
           for (int i = 1; i < isAbundantSum.length; i++){  
                if (!isAbundantSum[i]){  
                     sum += i;  
                }  
           }  
           System.out.println(sum);  
      }  
      private static int d(int number){  
           int sum = 1;  
           int sqrt = (int)Math.sqrt(number);  
           for (int i=2; i<=sqrt; i++){  
                if (number % i == 0){  
                     sum += (i + number / i);  
                }  
           }  
           if (sqrt * sqrt == number){  
                sum -= sqrt;  
           }  
           return sum;  
      }  
      private static boolean isAbundant(int number){  
           return d(number) > number;  
      }  

Saturday, 27 August 2016

Project Euler Problem 19: Counting Sundays

Problem

You are given the following information, but you may prefer to do some research for yourself.
  • 1 Jan 1900 was a Monday.
  • Thirty days has September,
    April, June and November.
    All the rest have thirty-one,
    Saving February alone,
    Which has twenty-eight, rain or shine.
    And on leap years, twenty-nine.
  • A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

Solution

Given the first day of the year and whether it's a leap year, the number of Sundays can be found quickly through a lookup.

      private static final int[] LEAP_YEAR_DAY = new int[7];  
      private static final int[] NONE_LEAP_YEAR_DAY = new int[7];  
      private static final int[] DAYS_IN_MONTH = {31,28,31,30,31,30,31,31,30,31,30}; //Jan - Nov   
      public static void main(String[] args) {  
           pattern(1900, NONE_LEAP_YEAR_DAY);  
           pattern(2000, LEAP_YEAR_DAY);  
           int firstDayOfYear = 1;  
           int totalSundays = 0;  
           for (int year=1901; year<=2000; year++){  
                firstDayOfYear = firstDayOfYear(firstDayOfYear, year-1);  
                totalSundays += numberSundays(firstDayOfYear, year);  
           }  
           System.out.print(totalSundays);  
      }  
      private static int firstDayOfYear(int previousYearFirstDay, int previousYear){  
           if (isLeapYear(previousYear)){  
                return (previousYearFirstDay + 366 % 7) % 7;  
           }  
           return (previousYearFirstDay + 365 % 7) % 7;  
      }  
      private static int numberSundays(int firstDay, int year){  
           int sundayIndex = (7 - firstDay) % 7;  
           return isLeapYear(year) ? LEAP_YEAR_DAY[sundayIndex] : NONE_LEAP_YEAR_DAY[sundayIndex];  
      }  
      private static void pattern(int year, int[] days) {  
           int nthDayInYear = 1; //1st Jan is the 1st day of the year  
           int firstDayOfMonth = 0; //1 is Monday, 0 being Sunday  
           days[firstDayOfMonth]++;   
           for (int i=0; i<DAYS_IN_MONTH.length; i++){  
                nthDayInYear += daysInMonth(i, year);  
                firstDayOfMonth = (nthDayInYear - 1) % 7;  
                days[firstDayOfMonth]++;  
           }  
      }  
      private static int daysInMonth(int i, int year) {  
           if (i != 1) { //Not Feb  
                return DAYS_IN_MONTH[i];  
           }  
           return isLeapYear(year) ? DAYS_IN_MONTH[i] + 1: DAYS_IN_MONTH[i];  
      }  
      private static boolean isLeapYear(int year) {  
           return (year % 100 != 0 && year % 4 ==0) || year % 400 == 0;  
      }  

Project Euler Problem 18 and 67: Maximum path sum

Problem

By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.
3
7 4
4 6
8 5 9 3
That is, 3 + 7 + 4 + 9 = 23.
Find the maximum total from top to bottom of the triangle below:
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23

Solution

Once again, don't use recursive prematurely!

This one requires working from bottom to top.

 private static final int ROW = 15;  
      private static final int[][] M = new int[ROW][ROW];  
      public static void main(String[] args) {  
           readFile();  
           for (int i=ROW-2; i >= 0; i--){  
                for (int j=0; j <= i; j++){  
                     M[i][j] = Math.max(M[i+1][j], M[i+1][j+1]) + M[i][j];  
                }  
           }  
           System.out.println(M[0][0]);       
      }  
      private static void readFile() {  
           File file = new File("Q18.txt");  
           try {  
                Scanner sc = new Scanner(file);  
                int i = 0;  
                while (sc.hasNextLine()) {  
                     int j = 0;  
                     Scanner lineSc = new Scanner(sc.nextLine());  
                     while (lineSc.hasNextInt()){  
                          M[i][j++]=lineSc.nextInt();       
                     }  
                     i++;  
                }  
                sc.close();  
           } catch (FileNotFoundException e) {  
                e.printStackTrace();  
           }  
      }