Problem:
福縞軒

「福縞軒」は行列のできる人気のラーメン屋です。でも最近、お客さんの間から「待ち時間が長いのに、店に入ったら空席があるのは許せない」という声が聞こえるようになってきました。どうしてそんな不満が出るのか調べたいのですが、お店が開いているあいだは忙しくて、実際の行列の様子を調べることができません。しかし、長年の経験からお客さんが来る間隔や人数は分かっているので、それをもとに待ち時間の分析をすることにしました。

店内にはカウンターに向かって 17 の席があります。開店時間は正午で、お客さんは次のようにやってきます。

0 番から 99 番までの 100 組のグループが来ます。

i 番目のグループは正午から 5i 分後にお店に到着します。

i 番目のグループの人数は i % 5 が 1 のとき 5 人、それ以外のときは 2 人です。

(x % yは x を y で割ったときの余りを表わします。)

i 番目のグループは、席に着くと 17(i % 2) + 3(i % 3) + 19 分間で食事を済ませます。

最初の 10 グループの到着時刻、人数、食事時間は次のようになります。

グループ番号

0

1

2

3

4

5

6

7

8

9

到着時刻(分後)

0

5

10

15

20

25

30

35

40

45

人数(人)

2

5

2

2

2

2

5

2

2

2

食事時間(分)

19

39

25

36

22

42

19

39

25

36

また、お客さんを席に案内するときには、次のようにしています。

席には 0 から 16 までの番号が付いています。

x 人のグループは連続して x 個あいている席があった時だけ着席できます。

また、座れる場所が複数あった場合は、席の番号が最も小さくなるところに座ります。例えば、0、1、2、4、5番の席だけが空いていた場合、5 人のグループは着席できません。2 人のグループであれば 0、1 番に着席します。

一度着席したら、席を移動してもらうことはしません。

お客さんは 1 分単位で出入りします。各時刻には次の順序でお客さんを案内します。

前のグループの離席と同時に次のグループの着席が可能となります。

お客さんを着席させる際には、行列の先頭にいるグループから順に、できる限り多くのグループを同じ時刻に着席させます。行列の順序を追い越すことはしません。つまり、先頭のグループが着席できなければ、行列内の他のグループが着席できたとしても、着席させません。

その時刻に到着したグループは、行列が残っている場合は行列の最後尾に並びます。行列が無く、着席できる場合は着席し、できない場合は並んで待ちます。例として最初の 10 グループが到着するまでの様子を示すと以下のようになります。各行の3つの欄は、左から時刻、座席の様子、行列の様子を示しています。座席は「_」が空席で、番号はその席にその番号のグループが座っていることを示しています。

時刻: 座席 行列
0: 00_______________:
5: 0011111__________:
10: 001111122________:
15: 00111112233______:
18: 00111112233______:
19: __111112233______:
20: 44111112233______:
25: 4411111223355____:
30: 4411111223355____: 66666 グループ6が到着
34: 4411111223355____: 66666
35: 4411111__3355____: 6666677 グループ7が到着
40: 4411111__3355____: 666667788 グループ8が到着
41: 4411111__3355____: 666667788
42: __11111__3355____: 666667788
43: __11111__3355____: 666667788
44: 6666677883355____: グループ6、7、8が着席
45: 666667788335599__: グループ9が到着、着席

例えば、時刻 40 では 8 番目のグループが到着しますが、着席できないので行列に加わります。4 番目のグループは時刻 41 まで食事をします。時刻 42 では、4 番目のグループの席が空きますが、連続した席数が足りないので 6 番目のグループはまだ着席できません。1 番目のグループは時刻 43 まで食事をします。時刻 44 で 1 番目のグループの席が空くので、6 番目のグループが着席し、同時に 7 番目、8 番目のグループも着席します。9 番目のグループは時刻 45 で到着し、席が空いているのでそのまま着席します。

これらの情報を基にして、0 以上 99 以下の整数 n を入力として、n 番目グループのお客さんが待つ時間(分単位)を出力するプログラムを作成してください。

Input

複数のデータセットが与えられます。各データセットは１つの整数 n からなります。

データセットの数は 20 を超えません。

Output

各データセットについて、n 番目のお客の分単位の待ち時間(0 以上の整数)を１行に出力してください。

Sample Input

5
6
7
8

Output for the Sample Input

0
14
9
4

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

class Main {

	public static void main(String... args) {
		List<Integer> targetGroupNumberList = getInputList();
		int maxGroupNumber = Collections.max(targetGroupNumberList);

		Fukushimaken fukushimaken = new Fukushimaken();
		List<Group> groupList = new ArrayList<Group>();

		int elapsedTime = 0;
		int groupNumber = 0;
		while (true) {
			if (elapsedTime % 5 == 0) {
				groupNumber = elapsedTime / 5;
				Group group = new Group(groupNumber);
				groupList.add(group);
				
				fukushimaken.receive(group);
			}
			fukushimaken.refresh(elapsedTime);

			if (maxGroupNumber <= groupNumber
					&& groupList.get(maxGroupNumber).haveStartedEating()) {
				// 対象となるグループ番号の待ち時間が全て取得できた段階で終了する
				break;
			}
			elapsedTime++;
		}

		for (int i : targetGroupNumberList) {
			Group group = groupList.get(i);
			int waitTime = group.getWaitTime();
			System.out.println(waitTime);
		}
	}
	
	static List<Integer> getInputList() {
		Scanner scanner = null;
		List<Integer> inputList = new ArrayList<Integer>();
		try {
			scanner = new Scanner(System.in);
			while (scanner.hasNext()) {
				String line = scanner.nextLine();
				inputList.add(Integer.parseInt(line));
			}
			return inputList;
		} finally {
			if (scanner != null) {
				scanner.close();
			}
		}
	}

	static class Fukushimaken {
		private List<Boolean> tables = new ArrayList<Boolean>(17); // 座席（Falseであれば空席となる）
		private List<Group> groupAtTable = new ArrayList<Group>(); // 着席しているグループ
		private LinkedList<Group> groupQueue = new LinkedList<Group>(); // 並んでいるグループ

		Fukushimaken() {
			for (int i = 0; i < 17; i++) {
				tables.add(false);
			}
		}

		void receive(Group group) {
			this.groupQueue.offer(group);
		}

		void refresh(int elapsedTime) {
			this.refreshTables(elapsedTime);
			this.refreshQueue(elapsedTime);
			for (Group group : this.groupQueue) {
				// 行列にいるグループに待ち時間を加算する
				group.addWaitTime();
			}
		}

		private void refreshTables(int elapsedTime) {
			// 食事の済んだグループの座席を空席とする
			for (int i = 0; i < this.groupAtTable.size(); i++) {
				Group group = this.groupAtTable.get(i);
				if (!group.haveFinishedMeal(elapsedTime)) {
					continue;
				}
				Set<Integer> tableNumbers = group.getUseTableNumbers();
				for (int j : tableNumbers) {
					this.tables.set(j, false);
				}
				this.groupAtTable.remove(i);
			}
		}

		private void refreshQueue(int elapsedTime) {
			Group group = this.groupQueue.peek();
			if (group == null) {
				return;
			}
			Set<Integer> emptyTableNumbers = this.getEmptyTablesNumbers(group.getSize());
			if (emptyTableNumbers.size() == 0) {
				return;
			}
			
			// 座席が空いていれば行列の先頭から順に着席する
			this.groupAtTable.add(group);
			group.startEating(emptyTableNumbers, elapsedTime);
			this.groupQueue.removeFirst();
			for (int i : emptyTableNumbers) {
				this.tables.set(i, true);
			}
			this.refreshQueue(elapsedTime);
		}

		private Set<Integer> getEmptyTablesNumbers(int size) {
			// 席の番号が小さいほうから空いている座席を探す
			Set<Integer> tableNumbers = new HashSet<Integer>();
			for (int i = 0; i < this.tables.size(); i++) {
				boolean isNotEmpty = this.tables.get(i);
				if (isNotEmpty) {
					tableNumbers.clear();
					continue;
				}
				tableNumbers.add(i);
				if (size <= tableNumbers.size()) {
					return tableNumbers;
				}
			}
			return new HashSet<Integer>();
		}
	}

	static class Group {

		private int number; // グループ番号
		private int timeToEat; // 食事にかかる時間
		private int endingTime; // 食事が済む時点の経過時間
		private Set<Integer> useTableNumbers; // 使用している座席の番号
		private int waitTime; // 待ち時間

		Group(int number) {
			this.number = number;
			this.timeToEat = 17 * (this.number % 2) + 3 * (this.number % 3) + 19;
		}

		void startEating(Set<Integer> tableNumbers, int elapsedTime) {
			// 着席し、さっそく食事を始める。この時点でこのグループの待ち時間は確定する。
			this.useTableNumbers = tableNumbers;
			this.endingTime = elapsedTime + timeToEat;
		}

		boolean haveFinishedMeal(int elapsedTime) {
			return this.endingTime < elapsedTime;
		}

		Set<Integer> getUseTableNumbers() {
			return this.useTableNumbers;
		}

		boolean haveStartedEating() {
			return this.useTableNumbers != null;
		}

		void addWaitTime() {
			this.waitTime++;
		}

		int getWaitTime() {
			// 店に到着した時点の1分間を除外して待ち時間を返す
			return (this.waitTime == 0) ? 0 : --this.waitTime;
		}

		int getSize() {
			return (this.number % 5 == 1) ? 5 : 2; // グループの人数
		}
	}
}