Last active
August 29, 2015 14:01
-
-
Save kazasiki/78c6a4c392cc009f755f to your computer and use it in GitHub Desktop.
CodeIQにて結城浩さん出題「チケットゴブル問題」の解答用コード。TicketGobble.javaがmainをもつクラスです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package package01; | |
/** | |
* 航空チケット。 | |
*/ | |
public class Ticket { | |
/** | |
* 国名 | |
*/ | |
public final String country; | |
/** | |
* 出発日 | |
*/ | |
public final int departure; | |
/** | |
* 到着日 | |
*/ | |
public final int arrival; | |
/** | |
* 出力文字列 | |
*/ | |
private final String OutputStr; | |
/** | |
* 国名、出発日、到着日を設定する | |
* | |
* @param country 国名 | |
* @param departure 出発日 | |
* @param arrival 到着日 | |
*/ | |
Ticket(String country, int departure, int arrival) { | |
this.country = country; | |
this.departure = departure; | |
this.arrival = arrival; | |
// 出力用の文字列を生成 | |
StringBuilder sb = new StringBuilder(country); | |
sb.append(" "); | |
calToSb(sb, departure); | |
sb.append("-"); | |
calToSb(sb, arrival); | |
OutputStr = sb.toString(); | |
} | |
/* (non-Javadoc) | |
* @see java.lang.Object#toString() | |
*/ | |
public String toString() { | |
return OutputStr; | |
} | |
/** | |
* 日付を文字列に変換する | |
* | |
* @param sb | |
* @param cal | |
*/ | |
private void calToSb(StringBuilder sb, int cal) { | |
sb.append(cal/100+1); | |
sb.append("/"); | |
sb.append(cal%100); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package package01; | |
import java.io.BufferedReader; | |
import java.io.IOException; | |
import java.nio.charset.Charset; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
import java.nio.file.Paths; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class TicketFileInput { | |
// private static final Path inputFile = Paths.get("five.txt"); | |
private static final Path inputFile = Paths.get("tickets.txt"); | |
/** | |
* 国名と日付の区切り文字 | |
*/ | |
private static final String COUNTRY_SEPARATE_STR = " "; | |
/** | |
* 開始日付と終了日付の区切り文字 | |
*/ | |
private static final String DATE_SEPARATE_STR = "-"; | |
/** | |
* 日付中の月と日の区切り文字 | |
*/ | |
private static final String DAY_SEPARATE_STR = "/"; | |
/** | |
* inputFileで指定されたファイルのチケット情報を読み込む。<br> | |
* 読込結果はチケット型のリストで返却する。<br> | |
* | |
* @return 読込結果のリスト | |
*/ | |
public static List<Ticket> parseFile() { | |
List<Ticket> ticketsList = new ArrayList<>(); | |
try { | |
BufferedReader br = Files.newBufferedReader(inputFile, Charset.defaultCharset()); | |
String str = br.readLine(); | |
while (str != null) { | |
ticketsList.add(getTicket(str)); | |
str = br.readLine(); | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
return ticketsList; | |
} | |
/** | |
* 1行のテキストをチケット型のインスタンスに変換する | |
* | |
* @param value 一行テキスト | |
* @return 変換結果のインスタンス | |
*/ | |
private static Ticket getTicket(String value) { | |
// 1行テキストから国名を取り出す | |
String[] splitText = value.split(COUNTRY_SEPARATE_STR); | |
String country = splitText[0]; | |
// 分割したテキストから日付を取り出す | |
splitText = splitText[1].split(DATE_SEPARATE_STR); | |
String departure = splitText[0]; | |
String arrival = splitText[1]; | |
int departureCal = getCalendar(departure); | |
int arrivalCal = getCalendar(arrival); | |
return new Ticket(country, departureCal, arrivalCal); | |
} | |
/** | |
* 日付の文字列を4桁の整数型に変換する。 | |
* | |
* @param dateString 日付の文字列 | |
* @return 変換後の4桁の整数型 | |
*/ | |
private static int getCalendar(String dateString) { | |
String[] splitStr = dateString.split(DAY_SEPARATE_STR); | |
String monthStr = splitStr[0]; | |
String dayStr = splitStr[1]; | |
int result = (Integer.parseInt(monthStr) - 1) * 100; | |
result += Integer.parseInt(dayStr); | |
return result; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package package01; | |
import java.util.List; | |
public class TicketGobble { | |
public static void main(String[] args) { | |
// ファイルからチケットの情報を読み取って、リスト型に変換する。 | |
List<Ticket> ticketList = TicketFileInput.parseFile(); | |
// 旅行プランをたてる。 | |
List<Ticket> optList = TicketPlan_Sorting.calcPlan(ticketList); | |
// 解答用の出力 | |
System.out.println(listToString(optList)); | |
} | |
/** | |
* チケットリストを文字列に変換して返却する<br> | |
* 文字列は「チケットの数:国名(スペース区切り)」となる<br> | |
* | |
* @param list チケットのリスト | |
* @return 「チケットの数:国名(スペース区切り)」の文字列 | |
*/ | |
public static String listToString(List<Ticket> list) { | |
StringBuilder sb = new StringBuilder((Integer.toString(list.size()))); | |
for (Ticket data : list) { | |
sb.append(" ").append(data.country); | |
} | |
return sb.toString(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package package01; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.List; | |
/** | |
* 日付順でのソートによって旅行プランをたてる。<br> | |
*/ | |
public class TicketPlan_Sorting { | |
/** | |
* チケットリストから「できるだけ多くの国に旅行するプラン」を求めて返却する | |
* | |
* @param ticketList チケットのリスト | |
* @return できるだけ多くの国に旅行するプラン | |
*/ | |
public static List<Ticket> calcPlan(List<Ticket> ticketList) { | |
// 引数のインスタンスは弄りたくないので、リストをシャローコピー | |
ArrayList<Ticket> sortedList = new ArrayList<>(ticketList); | |
// 日付順にソートをかける | |
Collections.sort(sortedList, TicketComparator.DATE_INSTANCE); | |
// 解答用のリスト | |
ArrayList<Ticket> plan = new ArrayList<>(sortedList.size()); | |
for (Ticket data : sortedList) { | |
if(plan.isEmpty()){ | |
plan.add(data); | |
} else { | |
Ticket last = plan.get(plan.size()-1); | |
if(data.departure > last.arrival){ | |
plan.add(data); | |
} else if(data.arrival < last.arrival){ | |
plan.remove(last); | |
plan.add(data); | |
} | |
} | |
} | |
// 国名順にソートをかける | |
Collections.sort(plan, TicketComparator.COUNTRY_INSTANCE); | |
return plan; | |
} | |
} | |
/** | |
* Ticketクラスの順序付けを行う比較関数です。<br> | |
* 国名順と日付順のインスタンスを用意しており、staticな定数として提供します。 | |
*/ | |
class TicketComparator implements Comparator<Ticket> { | |
private static final int SORT_MODE_COUNTRY = 0; | |
private static final int SORT_MODE_DATE = 1; | |
/** | |
* 国名順の比較関数インスタンス。 | |
*/ | |
public static final TicketComparator COUNTRY_INSTANCE = new TicketComparator(SORT_MODE_COUNTRY); | |
/** | |
* 日付順の比較関数インスタンス。<br> | |
* 出発日と到着日では出発日が優先されます。<br> | |
*/ | |
public static final TicketComparator DATE_INSTANCE = new TicketComparator(SORT_MODE_DATE); | |
private int sortMode; | |
private TicketComparator(int sortMode) { | |
this.sortMode = sortMode; | |
} | |
@Override | |
public int compare(Ticket o1, Ticket o2) { | |
switch (this.sortMode) { | |
case SORT_MODE_COUNTRY: | |
return o1.country.compareTo(o2.country); | |
case SORT_MODE_DATE: | |
int result = o1.departure - o2.departure; | |
if (result == 0) | |
return o1.arrival - o2.arrival; | |
else | |
return result; | |
default: | |
return 0; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment