Trains and Trails
It's been a while since you saw your friends and you are eager to meet them.
You all agreed to meet at a point, but each one of your friends could arrive at a different station.
You've arrived early, so you are waiting for your friends to come.
Since you are impatient, and have nothing better to do, you try to guess the place and order in which your friends will arrive, if they do.
You know each one of them is in a different train, labeled from A to Z.
So you take a look at the map:
A----\ 1
------\
B--¡------------2
C-------) ---/
D-------/ 3
The map leyend reads:
Character | Description | Time Value |
---|---|---|
0-9 |
Different stations | |
A-Z |
Different trains your friends are in | |
) |
Indicates a tunel. The trains that enter it will be lost | |
- |
Indicates a rail for the train to move forward | 1 |
\ |
Indicates a turn. The train will move down and forward | 2 |
/ |
Indicates a turn. The train will move up and forward | 2 |
¡ |
Indicates a traffic light. The train will wait 1 turn and continue | 3 |
In this example we can see that all the trains will arrive at station 2. So the trains there will be :
- Train A takes 21 units of time to arrive
- Train B takes 16 units of time to arrive
- Train D takes 17 units of time to arrive
- Train C goes into a tunnel so we dont count it
Having this in mind, our result will be:
{
'2' : ( 'B', 'D', 'A' )
}
In java the result is a Map\<Character,List\<Character\>\>
Edge cases:
- If 2 trains take the same time to arrive at the station, they should be ordered alphaberically
- Collisions between trains do not affect them
- If the trains get out of the map, dont count them
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.RepeatedTest; import java.util.Arrays; import java.util.Map; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import java.lang.Math; import java.util.Map.Entry; import java.util.Comparator; class SolutionTest { private String printTracks (char[][] tracks) { return Arrays.stream(tracks) .map(String::valueOf) .map(s -> String.join(s,"\n"+s)) .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) .toString(); } void pass(char[][] s, Map<Character, List<Character>> map) { assertEquals(map, TrainsAndRailways.travel(s), printTracks(s)); } void dontPass(char[][] s) { assertEquals(new java.util.HashMap<Character, List<Character>>(), TrainsAndRailways.travel(s), printTracks(s)); } @Test void exclusivePassTest() { pass(new char[][] {"A---------------1".toCharArray()}, Map.of('1', List.of('A'))); pass(new char[][] {"A----------¡-----1".toCharArray()}, Map.of('1', List.of('A'))); pass(new char[][] {"A-----------\\ -----------1".toCharArray(), " -------------/ ".toCharArray()}, Map.of('1', List.of('A'))); pass(new char[][] {"A-------- 1".toCharArray(), "B---------------2".toCharArray()}, Map.of('2', List.of('B'))); pass(new char[][] {"A----) 1".toCharArray(), "B-----------------2".toCharArray()}, Map.of('2', List.of('B'))); } @Test void exclusiveNotPassTest() { dontPass(new char[][] {"A-------- 1".toCharArray()}); dontPass(new char[][] {{}}); dontPass(new char[][] {"A----) 1".toCharArray()}); dontPass(new char[][] {"A----\\ ".toCharArray(), " --------1".toCharArray()}); dontPass(new char[][] {"A---------------------".toCharArray(), " 1".toCharArray()}); } private static char[][] generateRandomTracks() { char[][] matrix = new char[new Random().nextInt(5, 15)][new Random().nextInt(10, 25)]; int area = matrix.length * matrix[0].length; int numberOfStations = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 10); int numberOfTrains = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 26); int numberOfSemaphores = (int) new Random().nextDouble(area / 20, area / 8); int numberOfTunnels = (int) new Random().nextDouble(area / 30, area / 10); int numberOfLeftTracks = (int) new Random().nextDouble(area / 30, area / 15); int numberOfRightTracks = (int) new Random().nextDouble(area / 30, area / 15); List<Character> charsList = new ArrayList<Character>(); int i = 0; while (i < numberOfStations) { charsList.add(Character.forDigit(i++, 10)); } i = 0; while (i < numberOfTrains) { charsList.add((char) (i++ + 65)); } i = 0; while (i++ < numberOfSemaphores) { charsList.add('¡'); } i = 0; while (i++ < numberOfTunnels) { charsList.add(')'); } i = 0; while (i++ < numberOfLeftTracks) { charsList.add('/'); } i = 0; while (i++ < numberOfRightTracks) { charsList.add('\\'); } Collections.shuffle(charsList); int counter = 0; for (int x = 0; x < matrix.length; x++) { for (int y = 0; y < matrix[x].length; y++) { if ((charsList.get(counter) == '/' || charsList.get(counter) == '\\') && x != 0 && x != matrix.length - 1 && y != 0 && y != matrix[y].length) { matrix[x][y] = charsList.get(counter++); if (counter == charsList.size()) { counter = 0; } } } } for (int x = 0; x < matrix.length; x++) { for (int y = 0; y < matrix[x].length; y++) { if (matrix[x][y] == '\u0000') { matrix[x][y] = '-'; } } } return matrix; } @RepeatedTest(50) void randomTests() { char [][] matrix = generateRandomTracks(); assertEquals(travel(matrix), TrainsAndRailways.travel(matrix), printTracks(matrix)); } @Test void baseTest() { char[][] input = { {'A','-','-','-','-','-','\\','-','-','-','-','-','-','-','1'}, {'B','-','-','-','-','-','-','/',' '}, {' ',' ',' ',' ',' ',' ','-','-','-','-','-','2'}, {'C',' ','-','-','-','-','-','/',' '}, {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','3'}, {'D','-','-','-','-','-','-','-','-','-','-','-','-','-','4'} }; assertEquals(Map.of('1', List.of('B', 'A'), '4', List.of('D')), TrainsAndRailways.travel(input), printTracks(input)); char[][] input2 = { {'A', '-', '-', '¡', '\\', '¡', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {'B', '-', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {' ', ' ', ' ', ' ', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', }, {'C', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '1', }, {'D', '-', '-', '-', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', }, {'E', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', }, }; assertEquals(Map.of('1', List.of('C', 'B', 'A')), TrainsAndRailways.travel(input2), printTracks(input2)); char[][] input3 = { {'A', '-', '-', '-', '\\', '-', '-', '-', '1', }, {' ', ' ', ' ', ' ', '-', '-', '-', '-', '2', }, {'B', '-', '¡', '-', '/', ' ', '-', '/', ' ', }, {'C', '-', '-', '/', ' ', '-', '/', ' ', ' ', }, {' ', ' ', ' ', ' ', '-', '/', ' ', ' ', ' ', }, {'D', '-', '-', '-', '/', ' ', ' ', ' ', ' ', }, }; assertEquals(Map.of('2', List.of('A', 'C', 'B', 'D')), TrainsAndRailways.travel(input3), printTracks(input3)); char[][] input4 = { {'A', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {' ', ' ', ' ', ' ', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {'B', '-', '-', '-', '/', '-', '-', '-', '-', '\\', ' ', ' ', ' ', }, {'C', '-', '-', '¡', '-', '-', '-', '¡', '-', '-', '-', '-', '1', }, {'D', '-', '-', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', }, {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '-', '2', }, {'E', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', '-', '/', ' ', }, {' ', ' ', ' ', ' ', '-', '-', '-', '-', '-', '-', '/', ' ', ' ', }, {'F', '-', '-', '¡', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, }; assertEquals(Map.of('1', List.of('B','D','C'), '2', List.of('E', 'F')), TrainsAndRailways.travel(input4), printTracks(input4)); } @Test void moreTest() { char[][] input = { {'A', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '1', }, }; assertEquals(Map.of('1', List.of('A')), TrainsAndRailways.travel(input), printTracks(input)); char[][] input2 = { {'A', '¡', '¡', '¡', '¡', '¡', '\\', '¡', '¡', '¡', '¡', '¡', '1', }, {'B', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '2', }, }; assertEquals(Map.of('2', List.of('A', 'B')), TrainsAndRailways.travel(input2), printTracks(input2)); } @Test void edgeCases() { char[][] input1 = { {'A', '1', }, {'B', '2', }, {'C', '3', }, {'D', '4', }, {'E', '5', }, {'F', '6', }, }; assertEquals(Map.of('1', List.of('A'),'2', List.of('B'), '3', List.of('C'),'4', List.of('D'), '5', List.of('E'),'6', List.of('F') ), TrainsAndRailways.travel(input1), printTracks(input1)); char[][] input2 = { {'-', '-', '-', '-', '-', '-', '-', '\\', '-'}, {'A', '-', '-', '-', '/', '-', '-', '\\', ' ', }, {'B', '-', '-', '-', '-', '-', '-', '-', '1', }, {'-', '-', '-', '-', '-', '-', '-', '-', '-'}, }; assertEquals(Map.of('1', List.of('B')), TrainsAndRailways.travel(input2), printTracks(input2)); char[][] input3 = { {'A', '-', '-', '¡', '1', '-', '-', '-', '2', }, }; assertEquals(Map.of('1', List.of('A')), TrainsAndRailways.travel(input3), printTracks(input3)); char[][] input4 = { {'A', '-', '-', '-', '-', '-', '\\', '-', '-', '-', '-', '-', '\\', ' ', }, {'B', '¡', '¡', '-', '-', '-', '-', '/', '-', '-', '-', '-', '-', '1', }, {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {'C', '-', '-', '-', '¡', '-', '-', '-', '-', '-', '-', '-', '-', '2', }, }; assertEquals(Map.of('1', List.of('A','B'), '2', List.of('C')), TrainsAndRailways.travel(input4), printTracks(input4)); char[][] input5 = { {'A', '-', '-', '-', '-', '-', '-', ')', ' ', ' ', ' ', }, {'C', '-', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', }, {' ', ' ', ' ', ' ', ' ', '-', '-', '-', '-', '-', '1', }, {'B', '-', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', }, }; assertEquals(Map.of('1',List.of('B','C')), TrainsAndRailways.travel(input5), printTracks(input5)); } private Map<Character, List<Character>> travel(char[][] tracks) { Map<Character,List<Map.Entry<Character,Integer>>> result = new java.util.HashMap<>(); for (int row = 0; row < tracks.length; row++) { for (int column = 0; column < tracks[row].length; column++) { if (isTrain(tracks[row][column])) { Map.Entry<Character, Integer> train = new java.util.AbstractMap.SimpleEntry(tracks[row][column],0); goOnTraveling(tracks, row, column+1,train, result); } } } Map<Character,List<Character>> sortedShipOnStations = new java.util.HashMap<>(); result.forEach((k,v) -> sortedShipOnStations.put(k,sortTrains(v))); return sortedShipOnStations; } private boolean isTrain(char piece) { return piece >= 65 && piece <= 90; } private boolean isStation (char piece) { return piece >= 48 && piece <= 57; } private void goOnTraveling(char[][] tracks, int row, int column, Entry<Character, Integer> train, Map<Character, List<Map.Entry<Character, Integer>>> result) { while (column < tracks[row].length) { switch (tracks[row][column]) { case '¡': { train.setValue(train.getValue()+2); break; } case '-': { break; } case '/': { train.setValue(train.getValue()+1); row--; break; } case '\\': { train.setValue(train.getValue()+1); row++; break; } case ')': { return; } default: { if (isStation(tracks[row][column])) { result.putIfAbsent(tracks[row][column], new java.util.LinkedList<Map.Entry<Character,Integer>>()); result.get(tracks[row][column]).add(train); } return; } } train.setValue(train.getValue()+1); column++; } } private static List<Character> sortTrains (List<Entry<Character, Integer>> stationArrivals) { List<Character> orderedTrains = new java.util.LinkedList<>(); stationArrivals.forEach(e -> orderedTrains.add(e.getKey())); return stationArrivals.stream() .sorted(Comparator.comparing(Entry<Character, Integer>::getValue) .thenComparing(Entry::getKey)) .map(Map.Entry::getKey) .toList(); } }
- import org.junit.jupiter.api.Test;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import org.junit.jupiter.api.RepeatedTest;
- import java.util.Arrays;
- import java.util.Map;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.Random;
- import java.lang.Math;
import java.util.Map;- import java.util.Map.Entry;
- import java.util.Comparator;
- class SolutionTest {
- private String printTracks (char[][] tracks) {
- return Arrays.stream(tracks)
- .map(String::valueOf)
- .map(s -> String.join(s,"\n"+s))
- .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
- .toString();
- }
- void pass(char[][] s, Map<Character, List<Character>> map) {
- assertEquals(map, TrainsAndRailways.travel(s), printTracks(s));
- }
- void dontPass(char[][] s) {
- assertEquals(new java.util.HashMap<Character, List<Character>>(), TrainsAndRailways.travel(s), printTracks(s));
- }
- @Test
- void exclusivePassTest() {
- pass(new char[][] {"A---------------1".toCharArray()}, Map.of('1', List.of('A')));
- pass(new char[][] {"A----------¡-----1".toCharArray()}, Map.of('1', List.of('A')));
- pass(new char[][] {"A-----------\\ -----------1".toCharArray(),
- " -------------/ ".toCharArray()}, Map.of('1', List.of('A')));
- pass(new char[][] {"A-------- 1".toCharArray(), "B---------------2".toCharArray()}, Map.of('2', List.of('B')));
- pass(new char[][] {"A----) 1".toCharArray(), "B-----------------2".toCharArray()}, Map.of('2', List.of('B')));
- }
- @Test
- void exclusiveNotPassTest() {
- dontPass(new char[][] {"A-------- 1".toCharArray()});
- dontPass(new char[][] {{}});
- dontPass(new char[][] {"A----) 1".toCharArray()});
- dontPass(new char[][] {"A----\\ ".toCharArray(),
- " --------1".toCharArray()});
- dontPass(new char[][] {"A---------------------".toCharArray(),
- " 1".toCharArray()});
- }
- private static char[][] generateRandomTracks() {
- char[][] matrix = new char[new Random().nextInt(5, 15)][new Random().nextInt(10, 25)];
- int area = matrix.length * matrix[0].length;
- int numberOfStations = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 10);
- int numberOfTrains = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 26);
- int numberOfSemaphores = (int) new Random().nextDouble(area / 20, area / 8);
- int numberOfTunnels = (int) new Random().nextDouble(area / 30, area / 10);
- int numberOfLeftTracks = (int) new Random().nextDouble(area / 30, area / 15);
- int numberOfRightTracks = (int) new Random().nextDouble(area / 30, area / 15);
- List<Character> charsList = new ArrayList<Character>();
- int i = 0;
- while (i < numberOfStations) {
- charsList.add(Character.forDigit(i++, 10));
- }
- i = 0;
- while (i < numberOfTrains) {
- charsList.add((char) (i++ + 65));
- }
- i = 0;
- while (i++ < numberOfSemaphores) {
- charsList.add('¡');
- }
- i = 0;
- while (i++ < numberOfTunnels) {
- charsList.add(')');
- }
- i = 0;
- while (i++ < numberOfLeftTracks) {
- charsList.add('/');
- }
- i = 0;
- while (i++ < numberOfRightTracks) {
- charsList.add('\\');
- }
- Collections.shuffle(charsList);
- int counter = 0;
- for (int x = 0; x < matrix.length; x++) {
- for (int y = 0; y < matrix[x].length; y++) {
- if ((charsList.get(counter) == '/' || charsList.get(counter) == '\\') && x != 0 && x != matrix.length - 1 && y != 0 && y != matrix[y].length) {
- matrix[x][y] = charsList.get(counter++);
- if (counter == charsList.size()) {
- counter = 0;
- }
- }
- }
- }
- for (int x = 0; x < matrix.length; x++) {
- for (int y = 0; y < matrix[x].length; y++) {
- if (matrix[x][y] == '\u0000') {
- matrix[x][y] = '-';
- }
- }
- }
- return matrix;
- }
- @RepeatedTest(50)
- void randomTests() {
- char [][] matrix = generateRandomTracks();
- assertEquals(travel(matrix), TrainsAndRailways.travel(matrix), printTracks(matrix));
- }
- @Test
- void baseTest() {
- char[][] input = {
- {'A','-','-','-','-','-','\\','-','-','-','-','-','-','-','1'},
- {'B','-','-','-','-','-','-','/',' '},
- {' ',' ',' ',' ',' ',' ','-','-','-','-','-','2'},
- {'C',' ','-','-','-','-','-','/',' '},
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','3'},
- {'D','-','-','-','-','-','-','-','-','-','-','-','-','-','4'}
- };
- assertEquals(Map.of('1', List.of('B', 'A'), '4', List.of('D')), TrainsAndRailways.travel(input), printTracks(input));
- char[][] input2 = {
- {'A', '-', '-', '¡', '\\', '¡', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'B', '-', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {' ', ' ', ' ', ' ', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'C', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '1', },
- {'D', '-', '-', '-', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', },
- {'E', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', },
- };
- assertEquals(Map.of('1', List.of('C', 'B', 'A')), TrainsAndRailways.travel(input2), printTracks(input2));
- char[][] input3 = {
- {'A', '-', '-', '-', '\\', '-', '-', '-', '1', },
- {' ', ' ', ' ', ' ', '-', '-', '-', '-', '2', },
- {'B', '-', '¡', '-', '/', ' ', '-', '/', ' ', },
- {'C', '-', '-', '/', ' ', '-', '/', ' ', ' ', },
- {' ', ' ', ' ', ' ', '-', '/', ' ', ' ', ' ', },
- {'D', '-', '-', '-', '/', ' ', ' ', ' ', ' ', },
- };
- assertEquals(Map.of('2', List.of('A', 'C', 'B', 'D')), TrainsAndRailways.travel(input3), printTracks(input3));
- char[][] input4 = {
- {'A', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {' ', ' ', ' ', ' ', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'B', '-', '-', '-', '/', '-', '-', '-', '-', '\\', ' ', ' ', ' ', },
- {'C', '-', '-', '¡', '-', '-', '-', '¡', '-', '-', '-', '-', '1', },
- {'D', '-', '-', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', },
- {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '-', '2', },
- {'E', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', '-', '/', ' ', },
- {' ', ' ', ' ', ' ', '-', '-', '-', '-', '-', '-', '/', ' ', ' ', },
- {'F', '-', '-', '¡', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- };
- assertEquals(Map.of('1', List.of('B','D','C'), '2', List.of('E', 'F')), TrainsAndRailways.travel(input4), printTracks(input4));
- }
- @Test
- void moreTest() {
- char[][] input = {
- {'A', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '1', },
- };
- assertEquals(Map.of('1', List.of('A')), TrainsAndRailways.travel(input), printTracks(input));
- char[][] input2 = {
- {'A', '¡', '¡', '¡', '¡', '¡', '\\', '¡', '¡', '¡', '¡', '¡', '1', },
- {'B', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '2', },
- };
- assertEquals(Map.of('2', List.of('A', 'B')), TrainsAndRailways.travel(input2), printTracks(input2));
- }
- @Test
- void edgeCases() {
- char[][] input1 = {
- {'A', '1', },
- {'B', '2', },
- {'C', '3', },
- {'D', '4', },
- {'E', '5', },
- {'F', '6', },
- };
- assertEquals(Map.of('1', List.of('A'),'2', List.of('B'),
- '3', List.of('C'),'4', List.of('D'),
- '5', List.of('E'),'6', List.of('F')
- ), TrainsAndRailways.travel(input1), printTracks(input1));
- char[][] input2 = {
- {'-', '-', '-', '-', '-', '-', '-', '\\', '-'},
- {'A', '-', '-', '-', '/', '-', '-', '\\', ' ', },
- {'B', '-', '-', '-', '-', '-', '-', '-', '1', },
- {'-', '-', '-', '-', '-', '-', '-', '-', '-'},
- };
- assertEquals(Map.of('1', List.of('B')), TrainsAndRailways.travel(input2), printTracks(input2));
- char[][] input3 = {
- {'A', '-', '-', '¡', '1', '-', '-', '-', '2', },
- };
- assertEquals(Map.of('1', List.of('A')), TrainsAndRailways.travel(input3), printTracks(input3));
- char[][] input4 = {
- {'A', '-', '-', '-', '-', '-', '\\', '-', '-', '-', '-', '-', '\\', ' ', },
- {'B', '¡', '¡', '-', '-', '-', '-', '/', '-', '-', '-', '-', '-', '1', },
- {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'C', '-', '-', '-', '¡', '-', '-', '-', '-', '-', '-', '-', '-', '2', },
- };
- assertEquals(Map.of('1', List.of('A','B'), '2', List.of('C')), TrainsAndRailways.travel(input4), printTracks(input4));
- char[][] input5 = {
- {'A', '-', '-', '-', '-', '-', '-', ')', ' ', ' ', ' ', },
- {'C', '-', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', },
- {' ', ' ', ' ', ' ', ' ', '-', '-', '-', '-', '-', '1', },
- {'B', '-', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', },
- };
- assertEquals(Map.of('1',List.of('B','C')), TrainsAndRailways.travel(input5), printTracks(input5));
- }
- private Map<Character, List<Character>> travel(char[][] tracks) {
- Map<Character,List<Map.Entry<Character,Integer>>> result = new java.util.HashMap<>();
- for (int row = 0; row < tracks.length; row++) {
- for (int column = 0; column < tracks[row].length; column++) {
- if (isTrain(tracks[row][column])) {
- Map.Entry<Character, Integer> train = new java.util.AbstractMap.SimpleEntry(tracks[row][column],0);
- goOnTraveling(tracks, row, column+1,train, result);
- }
- }
- }
- Map<Character,List<Character>> sortedShipOnStations = new java.util.HashMap<>();
- result.forEach((k,v) -> sortedShipOnStations.put(k,sortTrains(v)));
- return sortedShipOnStations;
- }
- private boolean isTrain(char piece) {
- return piece >= 65 && piece <= 90;
- }
- private boolean isStation (char piece) {
- return piece >= 48 && piece <= 57;
- }
- private void goOnTraveling(char[][] tracks, int row, int column, Entry<Character, Integer> train, Map<Character, List<Map.Entry<Character, Integer>>> result) {
- while (column < tracks[row].length) {
- switch (tracks[row][column]) {
- case '¡': {
- train.setValue(train.getValue()+2);
- break;
- }
- case '-': {
- break;
- }
- case '/': {
- train.setValue(train.getValue()+1);
- row--;
- break;
- }
- case '\\': {
- train.setValue(train.getValue()+1);
- row++;
- break;
- }
- case ')': {
- return;
- }
- default: {
- if (isStation(tracks[row][column])) {
- result.putIfAbsent(tracks[row][column], new java.util.LinkedList<Map.Entry<Character,Integer>>());
- result.get(tracks[row][column]).add(train);
- }
- return;
- }
- }
- train.setValue(train.getValue()+1);
- column++;
- }
- }
- private static List<Character> sortTrains (List<Entry<Character, Integer>> stationArrivals) {
- List<Character> orderedTrains = new java.util.LinkedList<>();
- stationArrivals.forEach(e -> orderedTrains.add(e.getKey()));
- return stationArrivals.stream()
- .sorted(Comparator.comparing(Entry<Character, Integer>::getValue)
- .thenComparing(Entry::getKey))
- .map(Map.Entry::getKey)
- .toList();
- }
- }
Trains and Trails (RENFE)
It's been a while since you saw your friends and you are eager to meet them.
You all agreed to meet at a point, but each one of your friends could arrive at a different station.
You've arrived early, so you are waiting for your friends to come.
Since you are impatient, and have nothing better to do, you try to guess the place and order in which your friends will arrive, if they do.
You know each one of them is in a different train, labeled from A to Z.
So you take a look at the map:
A----\ 1
------\
B--¡------------2
C-------) ---/
D-------/ 3
The map leyend reads:
Character | Description | Time Value |
---|---|---|
0-9 |
Different stations | |
A-Z |
Different trains your friends are in | |
) |
Indicates a tunel. The trains that enter it will be lost | |
- |
Indicates a rail for the train to move forward | 1 |
\ |
Indicates a turn. The train will move down and forward | 2 |
/ |
Indicates a turn. The train will move up and forward | 2 |
¡ |
Indicates a traffic light. The train will wait 1 turn and continue | 3 |
In this example we can see that all the trains will arrive at station 2. So the trains there will be :
- Train A takes 21 units of time to arrive
- Train B takes 16 units of time to arrive
- Train D takes 17 units of time to arrive
- Train C goes into a tunnel so we dont count it
Having this in mind, our result will be ( dont return the empty stations ):
{
'2' : ( 'B', 'D', 'A' )
}
In java the result is a Map\<Character,List\<Character\>\>
Edge cases:
- If 2 trains take the same time to arrive at the station, they should be ordered alphaberically
- If not a single train arrives at the station, the list should be empty
- Collisions between trains do not affect them
- The trains dont get out of the map
import java.util.List; import java.util.Map; import java.util.Map.Entry; public class TrainsAndRailwaysv2 { public static Map<Character, List<Character>> travel(char[][] tracks) { Map<Character,List<Map.Entry<Character,Integer>>> result = new java.util.HashMap<>(); for (int row = 0; row < tracks.length; row++) { for (int column = 0; column < tracks[row].length; column++) { if (isTrain(tracks[row][column])) { Map.Entry<Character, Integer> train = new java.util.AbstractMap.SimpleEntry(tracks[row][column],0); goOnTraveling(tracks, row, column+1,train, result); } } } Map<Character,List<Character>> sortedShipOnStations = new java.util.HashMap<>(); result.forEach((k,v) -> sortedShipOnStations.put(k,sortTrains(v))); return sortedShipOnStations; } private static boolean isTrain(char piece) { return piece >= 65 && piece <= 90; } private static boolean isStation (char piece) { return piece >= 48 && piece <= 57; } private static void goOnTraveling(char[][] tracks, int row, int column, Entry<Character, Integer> train, Map<Character, List<Map.Entry<Character, Integer>>> result) { while (column < tracks[row].length) { switch (tracks[row][column]) { case '¡': { train.setValue(train.getValue()+2); column++; break; } case '-': { column++; break; } case '/': { train.setValue(train.getValue()+1); row--; break; } case '\\': { train.setValue(train.getValue()+1); row++; break; } case ')': { return; } default: { if (isStation(tracks[row][column])) { result.putIfAbsent(tracks[row][column], new java.util.LinkedList<Map.Entry<Character,Integer>>()); result.get(tracks[row][column]).add(train); } return; } } train.setValue(train.getValue()+1); } } private static List<Character> sortTrains (List<Entry<Character, Integer>> stationArrivals) { List<Character> orderedTrains = new java.util.LinkedList<>(); stationArrivals.forEach(e -> orderedTrains.add(e.getKey())); return stationArrivals.stream() .sorted((entry1,entry2) -> Integer.compare(entry1.getValue(), entry2.getValue())) .map(Entry::getKey) .toList(); } }
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- public class TrainsAndRailwaysv2 {
- public static Map<Character, List<Character>> travel(char[][] tracks) {
- Map<Character,List<Map.Entry<Character,Integer>>> result = new java.util.HashMap<>();
- for (int row = 0; row < tracks.length; row++) {
- for (int column = 0; column < tracks[row].length; column++) {
- if (isTrain(tracks[row][column])) {
- Map.Entry<Character, Integer> train = new java.util.AbstractMap.SimpleEntry(tracks[row][column],0);
- goOnTraveling(tracks, row, column+1,train, result);
- }
- }
- }
- Map<Character,List<Character>> sortedShipOnStations = new java.util.HashMap<>();
- result.forEach((k,v) -> sortedShipOnStations.put(k,sortTrains(v)));
return sortedShipOnStations;- return sortedShipOnStations;
- }
- private static boolean isTrain(char piece) {
- return piece >= 65 && piece <= 90;
- }
- private static boolean isStation (char piece) {
- return piece >= 48 && piece <= 57;
- }
- private static void goOnTraveling(char[][] tracks, int row, int column, Entry<Character, Integer> train, Map<Character, List<Map.Entry<Character, Integer>>> result) {
- while (column < tracks[row].length) {
- switch (tracks[row][column]) {
- case '¡': {
- train.setValue(train.getValue()+2);
- column++;
- break;
- }
- case '-': {
- column++;
- break;
- }
- case '/': {
- train.setValue(train.getValue()+1);
- row--;
- break;
- }
- case '\\': {
- train.setValue(train.getValue()+1);
- row++;
- break;
- }
- case ')': {
- return;
- }
- default: {
- if (isStation(tracks[row][column])) {
- result.putIfAbsent(tracks[row][column], new java.util.LinkedList<Map.Entry<Character,Integer>>());
- result.get(tracks[row][column]).add(train);
- }
- return;
- }
- }
- train.setValue(train.getValue()+1);
- }
- }
- private static List<Character> sortTrains (List<Entry<Character, Integer>> stationArrivals) {
- List<Character> orderedTrains = new java.util.LinkedList<>();
- stationArrivals.forEach(e -> orderedTrains.add(e.getKey()));
- return stationArrivals.stream()
- .sorted((entry1,entry2) ->
- Integer.compare(entry1.getValue(), entry2.getValue()))
- .map(Entry::getKey)
- .toList();
- }
}- }
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.RepeatedTest; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import java.lang.Math; import java.util.Map; import java.util.Map.Entry; class SolutionTest { void doIt(char[][] s, Map<Character, List<Character>> map) { String[] x = Arrays.stream(s).map(String::new).map(i-> String.join(i, "\n" +i)).toArray(String[]::new); assertEquals(map, TrainsAndRailwaysv2.travel(s), Arrays.toString(x) + ", map"); } void notDoIt(char[][] s) { assertEquals(new java.util.HashMap<Character, List<Character>>(), TrainsAndRailwaysv2.travel(s)); } @Test void esclusivePass() { doIt(new char[][] {"A---------------1".toCharArray()}, Map.of('1', List.of('A'))); doIt(new char[][] {"A----------¡-----1".toCharArray()}, Map.of('1', List.of('A'))); doIt(new char[][] {"A-----------\\ -----------1".toCharArray(), " -------------/ ".toCharArray()}, Map.of('1', List.of('A'))); doIt(new char[][] {"A-------- 1".toCharArray(), "B---------------2".toCharArray()}, Map.of('2', List.of('B'))); doIt(new char[][] {"A----) 1".toCharArray(), "B-----------------2".toCharArray()}, Map.of('2', List.of('B'))); } @Test void esclusiveNotPass() { notDoIt(new char[][] {"A-------- 1".toCharArray()}); notDoIt(new char[][] {{}}); notDoIt(new char[][] {"A----) 1".toCharArray()}); notDoIt(new char[][] {"A----\\ ".toCharArray(), " --------1".toCharArray()}); notDoIt(new char[][] {"A---------------------".toCharArray(), " 1".toCharArray()}); } private static char[][] generateRandomTracks() { char[][] matrix = new char[new Random().nextInt(5, 15)][new Random().nextInt(10, 25)]; int area = matrix.length * matrix[0].length; int numberOfStations = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 10); int numberOfTrains = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 26); int numberOfSemaphores = (int) new Random().nextDouble(area / 20, area / 8); int numberOfTunnels = (int) new Random().nextDouble(area / 30, area / 10); int numberOfLeftTracks = (int) new Random().nextDouble(area / 30, area / 15); int numberOfRightTracks = (int) new Random().nextDouble(area / 30, area / 15); List<Character> charsList = new ArrayList<Character>(); int i = 0; while (i < numberOfStations) { charsList.add(Character.forDigit(i++, 10)); } i = 0; while (i < numberOfTrains) { charsList.add((char) (i++ + 65)); } i = 0; while (i++ < numberOfSemaphores) { charsList.add('¡'); } i = 0; while (i++ < numberOfTunnels) { charsList.add(')'); } i = 0; while (i++ < numberOfLeftTracks) { charsList.add('/'); } i = 0; while (i++ < numberOfRightTracks) { charsList.add('\\'); } Collections.shuffle(charsList); int counter = 0; for (int x = 0; x < matrix.length; x++) { for (int y = 0; y < matrix[x].length; y++) { if ((charsList.get(counter) == '/' || charsList.get(counter) == '\\') && x != 0 && x != matrix.length - 1 && y != 0 && y != matrix[y].length) { matrix[x][y] = charsList.get(counter++); if (counter == charsList.size()) { counter = 0; } } } } for (int x = 0; x < matrix.length; x++) { for (int y = 0; y < matrix[x].length; y++) { if (matrix[x][y] == '\u0000') { matrix[x][y] = '-'; } } } return matrix; } @RepeatedTest(10) void randomTests() { char [][] matrix = generateRandomTracks(); assertEquals(travel(matrix), TrainsAndRailwaysv2.travel(matrix)); } @Test void baseTest() { char[][] input = { {'A','-','-','-','-','-','\\','-','-','-','-','-','-','-','1'}, {'B','-','-','-','-','-','-','/',' '}, {' ',' ',' ',' ',' ',' ','-','-','-','-','-','2'}, {'C',' ','-','-','-','-','-','/',' '}, {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','3'}, {'D','-','-','-','-','-','-','-','-','-','-','-','-','-','4'} }; assertEquals(Map.of('1', List.of('B', 'A'), '4', List.of('D')), TrainsAndRailwaysv2.travel(input)); char[][] input2 = { {'A', '-', '-', '¡', '\\', '¡', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {'B', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {' ', ' ', ' ', ' ', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', }, {'C', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '1', }, {'D', '-', '-', '-', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', }, {'E', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', }, }; assertEquals(Map.of('1', List.of('C', 'B', 'A')), TrainsAndRailwaysv2.travel(input2)); char[][] input3 = { {'A', '-', '-', '-', '\\', '-', '-', '-', '1', }, {' ', ' ', ' ', ' ', '-', '-', '-', '-', '2', }, {'B', '-', '¡', '-', '/', ' ', '-', '/', ' ', }, {'C', '-', '-', '/', ' ', '-', '/', ' ', ' ', }, {' ', ' ', ' ', ' ', '-', '/', ' ', ' ', ' ', }, {'D', '-', '-', '-', '/', ' ', ' ', ' ', ' ', }, }; assertEquals(Map.of('2', List.of('A', 'B', 'C', 'D')), TrainsAndRailwaysv2.travel(input3)); char[][] input4 = { {'A', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {' ', ' ', ' ', ' ', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {'B', '-', '-', '-', '/', '-', '-', '-', '-', '\\', ' ', ' ', ' ', }, {'C', '-', '-', '¡', '-', '-', '-', '¡', '-', '-', '-', '-', '1', }, {'D', '-', '-', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', }, {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '-', '2', }, {'E', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', '-', '/', ' ', }, {' ', ' ', ' ', ' ', '-', '-', '-', '-', '-', '-', '/', ' ', ' ', }, {'F', '-', '-', '¡', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, }; assertEquals(Map.of('1', List.of('C','D','B'), '2', List.of('E', 'F')), TrainsAndRailwaysv2.travel(input4)); } @Test void moreTest() { char[][] input = { {'A', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '1', }, }; assertEquals(Map.of('1', List.of('A')), TrainsAndRailwaysv2.travel(input)); char[][] input2 = { {'A', '¡', '¡', '¡', '¡', '¡', '\\', '¡', '¡', '¡', '¡', '¡', '1', }, {'B', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '2', }, }; assertEquals(Map.of('2', List.of('B', 'A')), TrainsAndRailwaysv2.travel(input2)); } @Test void edgeCases() { char[][] input1 = { {'A', '1', }, {'B', '2', }, {'C', '3', }, {'D', '4', }, {'E', '5', }, {'F', '6', }, }; assertEquals(Map.of('1', List.of('A'),'2', List.of('B'), '3', List.of('C'),'4', List.of('D'), '5', List.of('E'),'6', List.of('F') ), TrainsAndRailwaysv2.travel(input1)); char[][] input2 = { {'-', '-', '-', '-', '-', '-', '-', '\\', '-'}, {'A', '-', '-', '-', '/', '-', '-', '\\', ' ', }, {'B', '-', '-', '-', '-', '-', '-', '-', '1', }, {'-', '-', '-', '-', '-', '-', '-', '-', '-'}, }; assertEquals(Map.of('1', List.of('B', 'A')), TrainsAndRailwaysv2.travel(input2)); char[][] input3 = { {'A', '-', '-', '¡', '1', '-', '-', '-', '2', }, }; assertEquals(Map.of('1', List.of('A')), TrainsAndRailwaysv2.travel(input3)); char[][] input4 = { {'A', '-', '-', '-', '-', '-', '\\', '-', '-', '-', '-', '-', '\\', ' ', }, {'B', '¡', '¡', '-', '-', '-', '-', '/', '-', '-', '-', '-', '-', '1', }, {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, {'C', '-', '-', '-', '¡', '-', '-', '-', '-', '-', '-', '-', '-', '2', }, }; assertEquals(Map.of('1', List.of('A','B'), '2', List.of('C')), TrainsAndRailwaysv2.travel(input4)); } private Map<Character, List<Character>> travel(char[][] tracks) { Map<Character,List<Map.Entry<Character,Integer>>> result = new java.util.HashMap<>(); for (int row = 0; row < tracks.length; row++) { for (int column = 0; column < tracks[row].length; column++) { if (isTrain(tracks[row][column])) { Map.Entry<Character, Integer> train = new java.util.AbstractMap.SimpleEntry(tracks[row][column],0); goOnTraveling(tracks, row, column+1,train, result); } } } Map<Character,List<Character>> sortedShipOnStations = new java.util.HashMap<>(); result.forEach((k,v) -> sortedShipOnStations.put(k,sortTrains(v))); return sortedShipOnStations; } private boolean isTrain(char piece) { return piece >= 65 && piece <= 90; } private boolean isStation (char piece) { return piece >= 48 && piece <= 57; } private void goOnTraveling(char[][] tracks, int row, int column, Entry<Character, Integer> train, Map<Character, List<Map.Entry<Character, Integer>>> result) { while (column < tracks[row].length) { switch (tracks[row][column]) { case '¡': { train.setValue(train.getValue()+2); column++; break; } case '-': { column++; break; } case '/': { train.setValue(train.getValue()+1); row--; break; } case '\\': { train.setValue(train.getValue()+1); row++; break; } case ')': { return; } default: { if (isStation(tracks[row][column])) { result.putIfAbsent(tracks[row][column], new java.util.LinkedList<Map.Entry<Character,Integer>>()); result.get(tracks[row][column]).add(train); } return; } } train.setValue(train.getValue()+1); } } private List<Character> sortTrains (List<Entry<Character, Integer>> stationArrivals) { List<Character> orderedTrains = new java.util.LinkedList<>(); stationArrivals.forEach(e -> orderedTrains.add(e.getKey())); return stationArrivals.stream() .sorted((entry1,entry2) -> Integer.compare(entry1.getValue(), entry2.getValue())) .map(Entry::getKey) .toList(); } }
- import org.junit.jupiter.api.Test;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import org.junit.jupiter.api.RepeatedTest;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Map;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.Random;
- import org.junit.jupiter.api.RepeatedTest;
- import org.junit.jupiter.api.Test;
- import java.lang.Math;
- import java.util.Map;
- import java.util.Map.Entry;
- class SolutionTest {
- void doIt(char[][] s, Map<Character, List<Character>> map) {
- String[] x = Arrays.stream(s).map(String::new).map(i-> String.join(i, "\n" +i)).toArray(String[]::new);
- assertEquals(map, TrainsAndRailwaysv2.travel(s), Arrays.toString(x) + ", map");
- }
- void notDoIt(char[][] s) {
- assertEquals(new java.util.HashMap<Character, List<Character>>(), TrainsAndRailwaysv2.travel(s));
- }
- @Test
- void esclusivePass() {
- doIt(new char[][] {"A---------------1".toCharArray()}, Map.of('1', List.of('A')));
- doIt(new char[][] {"A----------¡-----1".toCharArray()}, Map.of('1', List.of('A')));
- doIt(new char[][] {"A-----------\\ -----------1".toCharArray(),
- " -------------/ ".toCharArray()}, Map.of('1', List.of('A')));
- doIt(new char[][] {"A-------- 1".toCharArray(), "B---------------2".toCharArray()}, Map.of('2', List.of('B')));
- doIt(new char[][] {"A----) 1".toCharArray(), "B-----------------2".toCharArray()}, Map.of('2', List.of('B')));
- }
- @Test
- void esclusiveNotPass() {
- notDoIt(new char[][] {"A-------- 1".toCharArray()});
- notDoIt(new char[][] {{}});
- notDoIt(new char[][] {"A----) 1".toCharArray()});
- notDoIt(new char[][] {"A----\\ ".toCharArray(),
- " --------1".toCharArray()});
- notDoIt(new char[][] {"A---------------------".toCharArray(),
- " 1".toCharArray()});
- }
- private static char[][] generateRandomTracks() {
- char[][] matrix = new char[new Random().nextInt(5, 15)][new Random().nextInt(10, 25)];
- int area = matrix.length * matrix[0].length;
- int numberOfStations = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 10);
- int numberOfTrains = Math.min((int) new Random().nextDouble( 0.5 * matrix.length,matrix.length), 26);
- int numberOfSemaphores = (int) new Random().nextDouble(area / 20, area / 8);
- int numberOfTunnels = (int) new Random().nextDouble(area / 30, area / 10);
- int numberOfLeftTracks = (int) new Random().nextDouble(area / 30, area / 15);
- int numberOfRightTracks = (int) new Random().nextDouble(area / 30, area / 15);
- List<Character> charsList = new ArrayList<Character>();
- int i = 0;
- while (i < numberOfStations) {
- charsList.add(Character.forDigit(i++, 10));
- }
- i = 0;
- while (i < numberOfTrains) {
- charsList.add((char) (i++ + 65));
- }
- i = 0;
- while (i++ < numberOfSemaphores) {
- charsList.add('¡');
- }
- i = 0;
- while (i++ < numberOfTunnels) {
- charsList.add(')');
- }
- i = 0;
- while (i++ < numberOfLeftTracks) {
- charsList.add('/');
- }
- i = 0;
- while (i++ < numberOfRightTracks) {
- charsList.add('\\');
- }
- Collections.shuffle(charsList);
- int counter = 0;
- for (int x = 0; x < matrix.length; x++) {
- for (int y = 0; y < matrix[x].length; y++) {
- if ((charsList.get(counter) == '/' || charsList.get(counter) == '\\') && x != 0 && x != matrix.length - 1 && y != 0 && y != matrix[y].length) {
- matrix[x][y] = charsList.get(counter++);
- if (counter == charsList.size()) {
- counter = 0;
- }
- }
- }
- }
- for (int x = 0; x < matrix.length; x++) {
- for (int y = 0; y < matrix[x].length; y++) {
- if (matrix[x][y] == '\u0000') {
- matrix[x][y] = '-';
- }
- }
- }
- return matrix;
- }
- @RepeatedTest(10)
- void randomTests() {
- char [][] matrix = generateRandomTracks();
- assertEquals(travel(matrix), TrainsAndRailwaysv2.travel(matrix));
- }
- @Test
- void baseTest() {
- char[][] input = {
- {'A','-','-','-','-','-','\\','-','-','-','-','-','-','-','1'},
- {'B','-','-','-','-','-','-','/',' '},
- {' ',' ',' ',' ',' ',' ','-','-','-','-','-','2'},
- {'C',' ','-','-','-','-','-','/',' '},
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','3'},
- {'D','-','-','-','-','-','-','-','-','-','-','-','-','-','4'}
- };
- assertEquals(Map.of('1', List.of('B', 'A'), '4', List.of('D')), TrainsAndRailwaysv2.travel(input));
- char[][] input2 = {
- {'A', '-', '-', '¡', '\\', '¡', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'B', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {' ', ' ', ' ', ' ', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'C', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '1', },
- {'D', '-', '-', '-', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', },
- {'E', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', },
- };
- assertEquals(Map.of('1', List.of('C', 'B', 'A')), TrainsAndRailwaysv2.travel(input2));
- char[][] input3 = {
- {'A', '-', '-', '-', '\\', '-', '-', '-', '1', },
- {' ', ' ', ' ', ' ', '-', '-', '-', '-', '2', },
- {'B', '-', '¡', '-', '/', ' ', '-', '/', ' ', },
- {'C', '-', '-', '/', ' ', '-', '/', ' ', ' ', },
- {' ', ' ', ' ', ' ', '-', '/', ' ', ' ', ' ', },
- {'D', '-', '-', '-', '/', ' ', ' ', ' ', ' ', },
- };
- assertEquals(Map.of('2', List.of('A', 'B', 'C', 'D')), TrainsAndRailwaysv2.travel(input3));
- char[][] input4 = {
- {'A', '-', '-', '-', ')', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {' ', ' ', ' ', ' ', '-', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'B', '-', '-', '-', '/', '-', '-', '-', '-', '\\', ' ', ' ', ' ', },
- {'C', '-', '-', '¡', '-', '-', '-', '¡', '-', '-', '-', '-', '1', },
- {'D', '-', '-', '-', '-', '-', '/', ' ', ' ', ' ', ' ', ' ', ' ', },
- {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '-', '2', },
- {'E', '-', '-', '-', '\\', ' ', ' ', ' ', ' ', ' ', '-', '/', ' ', },
- {' ', ' ', ' ', ' ', '-', '-', '-', '-', '-', '-', '/', ' ', ' ', },
- {'F', '-', '-', '¡', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- };
- assertEquals(Map.of('1', List.of('C','D','B'), '2', List.of('E', 'F')), TrainsAndRailwaysv2.travel(input4));
- }
- @Test
- void moreTest() {
- char[][] input = {
- {'A', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '1', },
- };
- assertEquals(Map.of('1', List.of('A')), TrainsAndRailwaysv2.travel(input));
- char[][] input2 = {
- {'A', '¡', '¡', '¡', '¡', '¡', '\\', '¡', '¡', '¡', '¡', '¡', '1', },
- {'B', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '¡', '2', },
- };
- assertEquals(Map.of('2', List.of('B', 'A')), TrainsAndRailwaysv2.travel(input2));
- }
- @Test
- void edgeCases() {
- char[][] input1 = {
- {'A', '1', },
- {'B', '2', },
- {'C', '3', },
- {'D', '4', },
- {'E', '5', },
- {'F', '6', },
- };
- assertEquals(Map.of('1', List.of('A'),'2', List.of('B'),
- '3', List.of('C'),'4', List.of('D'),
- '5', List.of('E'),'6', List.of('F')
- ), TrainsAndRailwaysv2.travel(input1));
- char[][] input2 = {
- {'-', '-', '-', '-', '-', '-', '-', '\\', '-'},
- {'A', '-', '-', '-', '/', '-', '-', '\\', ' ', },
- {'B', '-', '-', '-', '-', '-', '-', '-', '1', },
- {'-', '-', '-', '-', '-', '-', '-', '-', '-'},
- };
- assertEquals(Map.of('1', List.of('B', 'A')), TrainsAndRailwaysv2.travel(input2));
- char[][] input3 = {
- {'A', '-', '-', '¡', '1', '-', '-', '-', '2', },
- };
- assertEquals(Map.of('1', List.of('A')), TrainsAndRailwaysv2.travel(input3));
- char[][] input4 = {
- {'A', '-', '-', '-', '-', '-', '\\', '-', '-', '-', '-', '-', '\\', ' ', },
- {'B', '¡', '¡', '-', '-', '-', '-', '/', '-', '-', '-', '-', '-', '1', },
- {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', },
- {'C', '-', '-', '-', '¡', '-', '-', '-', '-', '-', '-', '-', '-', '2', },
- };
- assertEquals(Map.of('1', List.of('A','B'), '2', List.of('C')), TrainsAndRailwaysv2.travel(input4));
- }
- private Map<Character, List<Character>> travel(char[][] tracks) {
- Map<Character,List<Map.Entry<Character,Integer>>> result = new java.util.HashMap<>();
- for (int row = 0; row < tracks.length; row++) {
- for (int column = 0; column < tracks[row].length; column++) {
- if (isTrain(tracks[row][column])) {
- Map.Entry<Character, Integer> train = new java.util.AbstractMap.SimpleEntry(tracks[row][column],0);
- goOnTraveling(tracks, row, column+1,train, result);
- }
- }
- }
- Map<Character,List<Character>> sortedShipOnStations = new java.util.HashMap<>();
- result.forEach((k,v) -> sortedShipOnStations.put(k,sortTrains(v)));
- return sortedShipOnStations;
- }
- private boolean isTrain(char piece) {
- return piece >= 65 && piece <= 90;
- }
- private boolean isStation (char piece) {
- return piece >= 48 && piece <= 57;
- }
- private void goOnTraveling(char[][] tracks, int row, int column, Entry<Character, Integer> train, Map<Character, List<Map.Entry<Character, Integer>>> result) {
- while (column < tracks[row].length) {
- switch (tracks[row][column]) {
- case '¡': {
- train.setValue(train.getValue()+2);
- column++;
- break;
- }
- case '-': {
- column++;
- break;
- }
- case '/': {
- train.setValue(train.getValue()+1);
- row--;
- break;
- }
- case '\\': {
- train.setValue(train.getValue()+1);
- row++;
- break;
- }
- case ')': {
- return;
- }
- default: {
- if (isStation(tracks[row][column])) {
- result.putIfAbsent(tracks[row][column], new java.util.LinkedList<Map.Entry<Character,Integer>>());
- result.get(tracks[row][column]).add(train);
- }
- return;
- }
- }
- train.setValue(train.getValue()+1);
- }
- }
- private List<Character> sortTrains (List<Entry<Character, Integer>> stationArrivals) {
- List<Character> orderedTrains = new java.util.LinkedList<>();
- stationArrivals.forEach(e -> orderedTrains.add(e.getKey()));
- return stationArrivals.stream()
- .sorted((entry1,entry2) ->
- Integer.compare(entry1.getValue(), entry2.getValue()))
- .map(Entry::getKey)
- .toList();
- }
- }
Trains and Trails (RENFE)
It's been a while since you saw your friends and you are eager to meet them.
You all agreed to meet at a point, but each one of your friends could arrive at a different station.
You've arrived early, so you are waiting for your friends to come.
Since you are impatient, and have nothing better to do, you try to guess the place and order in which your friends will arrive, if they do.
You know each one of them is in a different train, labeled from A to Z.
So you take a look at the map:
A----\ 1
------\
B--¡------------2
C-------) ---/
D-------/ 3
The map leyend reads:
Character | Description | Time Value |
---|---|---|
0-9 |
Different stations | |
A-Z |
Different trains your friends are in | |
) |
Indicates a tunel. The trains that enter it will be lost | |
- |
Indicates a rail for the train to move forward | 1 |
\ |
Indicates a turn. The train will move down and forward | 2 |
/ |
Indicates a turn. The train will move up and forward | 2 |
¡ |
Indicates a traffic light. The train will wait 1 turn and continue | 3 |
In this example we can see that all the trains will arrive at station 2. So the trains there will be :
- Train A takes 21 units of time to arrive
- Train B takes 16 units of time to arrive
- Train D takes 17 units of time to arrive
- Train C goes into a tunnel so we dont count it
Having this in mind, our result will be:
{
'2' : ( 'B', 'D', 'A' )
}
In java the result is a Map\<Character,List\<Character\>\>
Edge cases:
- If 2 trains take the same time to arrive at the station, they should be ordered alphaberically
- Collisions between trains do not affect them
- If the trains get out of the map, dont count them
import java.util.List; import java.util.Map; //Added description public class TrainsAndRailwaysv2 { public static Map<Character, List<Character>> travel(char[][] tracks) { return null; } }
- import java.util.List;
- import java.util.Map;
- //Added description
- public class TrainsAndRailwaysv2 {
- public static Map<Character, List<Character>> travel(char[][] tracks) {
- return null;
- }
- }
let isPerfectSquare: (Int) -> Bool = { sqrt(Double($0)).truncatingRemainder(dividingBy: 1) == 0 }
func isPerfectSquare(_ input: Int) -> Bool {let inputAsDouble = Double(input)return inputAsDouble.squareRoot().rounded() == inputAsDouble.squareRoot()}- let isPerfectSquare: (Int) -> Bool = { sqrt(Double($0)).truncatingRemainder(dividingBy: 1) == 0 }
class Solution{ static boolean isPerfectSquare(int num){ return Math.sqrt(num) % 1 == 0; } }
func isPerfectSquare(_ input: Int) -> Bool {let inputAsDouble = Double(input)return inputAsDouble.squareRoot().rounded() == inputAsDouble.squareRoot()- class Solution{
- static boolean isPerfectSquare(int num){ return Math.sqrt(num) % 1 == 0; }
- }
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; class SolutionTest { @Test void testNumbersFrom0To10() { assertEquals(Solution.isPerfectSquare(0), true, "0"); assertEquals(Solution.isPerfectSquare(1), true, "1"); assertEquals(Solution.isPerfectSquare(2), false, "2"); assertEquals(Solution.isPerfectSquare(3), false, "3"); assertEquals(Solution.isPerfectSquare(4), true, "4"); assertEquals(Solution.isPerfectSquare(5), false, "5"); assertEquals(Solution.isPerfectSquare(6), false, "6"); assertEquals(Solution.isPerfectSquare(7), false, "7"); assertEquals(Solution.isPerfectSquare(8), false, "8"); assertEquals(Solution.isPerfectSquare(9), true, "9"); assertEquals(Solution.isPerfectSquare(10), false, "10"); } }
import XCTest// XCTest Spec Example:// TODO: replace with your own tests (TDD), these are just how-to examples to get you started- import org.junit.jupiter.api.Test;
class SolutionTest: XCTestCase {static var allTests = [("Test Numbers From 0 To 10", testNumbersFrom0To10),]- import static org.junit.jupiter.api.Assertions.assertEquals;
func testNumbersFrom0To10() {XCTAssertEqual(isPerfectSquare(0), true, "0")XCTAssertEqual(isPerfectSquare(1), true, "1")XCTAssertEqual(isPerfectSquare(2), false, "2")XCTAssertEqual(isPerfectSquare(3), false, "3")XCTAssertEqual(isPerfectSquare(4), true, "4")XCTAssertEqual(isPerfectSquare(5), false, "5")XCTAssertEqual(isPerfectSquare(6), false, "6")XCTAssertEqual(isPerfectSquare(7), false, "7")XCTAssertEqual(isPerfectSquare(8), false, "8")XCTAssertEqual(isPerfectSquare(9), true, "9")XCTAssertEqual(isPerfectSquare(10), false, "10")- class SolutionTest {
- @Test
- void testNumbersFrom0To10() {
- assertEquals(Solution.isPerfectSquare(0), true, "0");
- assertEquals(Solution.isPerfectSquare(1), true, "1");
- assertEquals(Solution.isPerfectSquare(2), false, "2");
- assertEquals(Solution.isPerfectSquare(3), false, "3");
- assertEquals(Solution.isPerfectSquare(4), true, "4");
- assertEquals(Solution.isPerfectSquare(5), false, "5");
- assertEquals(Solution.isPerfectSquare(6), false, "6");
- assertEquals(Solution.isPerfectSquare(7), false, "7");
- assertEquals(Solution.isPerfectSquare(8), false, "8");
- assertEquals(Solution.isPerfectSquare(9), true, "9");
- assertEquals(Solution.isPerfectSquare(10), false, "10");
- }
- }
XCTMain([testCase(SolutionTest.allTests)])