001package ball.riddler538.ant.taskdefs; 002/*- 003 * ########################################################################## 004 * Solutions for the 538 Riddler 005 * %% 006 * Copyright (C) 2015 - 2022 Allen D. Ball 007 * %% 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 * ########################################################################## 020 */ 021import ball.util.ant.taskdefs.AntTask; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.List; 025import java.util.Random; 026import lombok.NoArgsConstructor; 027import lombok.ToString; 028import org.apache.tools.ant.BuildException; 029 030/** 031 * {@link.uri http://ant.apache.org/ Ant} {@link org.apache.tools.ant.Task} 032 * to solve 033 * {@link.uri 034 * http://fivethirtyeight.com/features/how-long-will-your-smartphone-distract-you-from-family-dinner/ 035 * How Long Will Your Smartphone Distract You From Family Dinner?} 036 * <p> 037 * You’ve just finished unwrapping your holiday presents. You and your 038 * sister got brand-new smartphones, opening them at the same moment. You 039 * immediately both start doing important tasks on the Internet, and each 040 * task you do takes one to five minutes. (All tasks take exactly one, two, 041 * three, four or five minutes, with an equal probability of each). After 042 * each task, you have a brief moment of clarity. During these, you remember 043 * that you and your sister are supposed to join the rest of the family for 044 * dinner and that you promised each other you’d arrive together. You ask if 045 * your sister is ready to eat, but if she is still in the middle of a task, 046 * she asks for time to finish it. In that case, you now have time to kill, 047 * so you start a new task (again, it will take one, two, three, four or 048 * five minutes, exactly, with an equal probability of each). If she asks 049 * you if it’s time for dinner while you’re still busy, you ask for time to 050 * finish up and she starts a new task and so on. From the moment you first 051 * open your gifts, how long on average does it take for both of you to be 052 * between tasks at the same time so you can finally eat? (You can assume 053 * the “moments of clarity” are so brief as to take no measurable time at 054 * all.) 055 * </p> 056 * Solution uses the Monte Carlo method. 057 * 058 * {@ant.task} 059 * 060 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 061 */ 062@AntTask("solve-riddle-2015-12-22") 063@NoArgsConstructor @ToString 064public class SolveRiddle20151222Task extends AbstractSimulationTask { 065 @Override 066 public void execute() throws BuildException { 067 super.execute(); 068 069 try { 070 ArrayList<Try> tries = new ArrayList<>(getCount()); 071 072 for (int i = 0, n = getCount(); i < n; i += 1) { 073 tries.add(new Try()); 074 } 075 076 int min = tries.get(0).duration(); 077 int max = tries.get(0).duration(); 078 int sum = 0; 079 080 for (Try tryN : tries) { 081 int duration = tryN.duration(); 082 083 min = Math.min(min, duration); 084 max = Math.max(max, duration); 085 sum += duration; 086 } 087 088 log("count: " + tries.size()); 089 log("min: " + min); 090 log("max: " + max); 091 log("average: " + (((float) sum) / tries.size())); 092 } catch (BuildException exception) { 093 throw exception; 094 } catch (Throwable throwable) { 095 throwable.printStackTrace(); 096 throw new BuildException(throwable); 097 } 098 } 099 100 private static final Random RANDOM = new Random(); 101 private static final List<Integer> DURATIONS = 102 Arrays.asList(1, 2, 3, 4 ,5); 103 104 @ToString 105 private class Try { 106 private List<Integer> you = new ArrayList<>(); 107 private List<Integer> sister = new ArrayList<>(); 108 109 public Try() { 110 for (;;) { 111 if (sum(you) < sum(sister)) { 112 you.add(DURATIONS.get(RANDOM.nextInt(DURATIONS.size()))); 113 } else { 114 sister.add(DURATIONS.get(RANDOM.nextInt(DURATIONS.size()))); 115 } 116 117 if (sum(you) == sum(sister)) { 118 break; 119 } 120 } 121 } 122 123 public int duration() { return sum(you); } 124 125 private int sum(List<Integer> list) { 126 int total = 0; 127 128 for (Integer element : list) { 129 total += element; 130 } 131 132 return total; 133 } 134 } 135}