/** * Prisoner.java * * Copyright 2014 the original author or authors. * * We licenses this file to you under the Apache License, version 2.0 * (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.apache.niolex.common.prisoner; import java.util.Random; /** * @author <a href="mailto:xiejiyun@foxmail.com">Xie, Jiyun</a> * @version 1.0.0 * @since 2014-1-8 */ public class FuncPrisoner { // The single light private static boolean light = false; private static int[] prisoners = new int[100]; private static int[] prisoners_out = new int[100]; public static int oneRound(Random generator, final int io) throws Exception { light = false; for (int i = 0; i < 100; ++i) { prisoners[i] = 1; prisoners_out[i] = 0; } int i = 1; simpleOneCollector = 0; switch (io) { case 0: while (!simpleOne(i, generator.nextInt(100))) { ++i; } break; case 1: while (!simpleKth(i, generator.nextInt(100))) { ++i; } break; case 2: while (!splitNth(i, generator.nextInt(100))) { ++i; } break; case 3: while (!split10to2(i, generator.nextInt(100))) { ++i; } break; } return i; } private static int simpleOneCollector = 0; public static boolean simpleOne(int day, int k) { if (k != simpleOneCollector) { if (!light && prisoners[k] == 1) { --prisoners[k]; light = true; } } else if (light) { light = false; ++prisoners[k]; if (prisoners[k] == 100) { return true; } } return false; } public static boolean simpleKth(int day, int k) { if (day < 101) { if (day == 100 && !light) { return true; } if (light) { return false; } ++prisoners_out[k]; --prisoners[k]; if (prisoners_out[k] == 2) { // The collector found. simpleOneCollector = k; light = true; prisoners[k] = day - 2; } return false; } else { return simpleOne(day, k); } } private static final int PHASE_LENGTH = 450; public static boolean splitNth(int day, final int k) { // We start from 0. --day; int iteration = (day / PHASE_LENGTH) % 7; final int cnt = 1 << iteration; final boolean lastDay = (day % PHASE_LENGTH) == (PHASE_LENGTH - 1); if (k != simpleOneCollector) { if (light) { if ((prisoners[k] & cnt) > 0 || lastDay) { prisoners[k] += cnt; light = false; } } else { // light is off, check today mask. if ((prisoners[k] & cnt) > 0 && !lastDay) { prisoners[k] -= cnt; light = true; } } } else if (light) { light = false; prisoners[k] += cnt; if (prisoners[k] == 100) { return true; } } return false; } private static final int PHASE_1 = 450; private static final int PHASE_2 = 450; private static final int PHASE_TOTAL = PHASE_1 + PHASE_2; public static boolean split10to2(int day, final int k) { // We start from 0. --day; final int remind = day % PHASE_TOTAL; final int phase = remind < PHASE_1 ? 1 : 2; if (remind == PHASE_1 - 1) { if (light) { ++prisoners[k]; light = false; if (k == 0 && prisoners[k] % 10 == 0) { ++prisoners_out[k]; } } return prisoners[k] == 100; } else if (remind == PHASE_TOTAL - 1) { if (light) { prisoners[k] += 10; --prisoners_out[k]; light = false; } return prisoners[k] == 100; } if (phase == 1) { // collect all if (k < 10) { if (light && prisoners_out[k] <= 0 && prisoners[k] % 10 != 0) { ++prisoners[k]; light = false; if (k == 0 && prisoners[k] % 10 == 0) { ++prisoners_out[k]; } return prisoners[k] == 100; } if (!light && prisoners_out[k] > 0 && prisoners[k] % 10 != 0) { --prisoners[k]; light = true; } } else { if (!light && prisoners[k] != 10 && prisoners[k] % 10 > 0) { --prisoners[k]; light = true; } } } else { // collect to base if (k == 0) { if (light) { prisoners[k] += 10; light = false; return prisoners[k] == 100; } } else { if (!light && prisoners[k] >= 10) { prisoners[k] -= 10; ++prisoners_out[k]; light = true; } } } return false; } /** * @param args */ public static void main(String[] args) throws Exception { double base = 365000.2; double base2 = 365.0002; for (int io = 0; io < 4; ++io) { int total = 0, max = 0, min = Integer.MAX_VALUE, k; Random generator = new Random(32785); for (int i = 0; i < 1000; ++i) { k = oneRound(generator, io); total += k; if (max < k) max = k; if (min > k) min = k; } System.out.printf("%s\t - Avg %.2fY, Max %.2fY, Min %5.2fY\n", getName(io), (total / base), (max / base2), (min / base2)); } } /** * @param io * @return */ private static Object getName(int io) { switch (io) { case 0: return "simpleOne"; case 1: return "simpleKth"; case 2: return "splitNth"; case 3: return "split10to2"; } return null; } }