├── .gitignore ├── CodeWars.iml ├── README.md └── src └── main └── java ├── kyu3 ├── BattleField.java ├── Dinglemouse.java ├── MakeASpiral.java └── RailFenceCipher.java ├── kyu4 ├── Boggle.java ├── ConwayLife.java ├── HowManyNumbers.java ├── LongestSlideDown.java ├── SecretDetective.java ├── SnailSort.java ├── StringsMix.java ├── StripComments.java ├── SudokuSolutionValidator.java ├── TimeFormatter.java └── TopWords.java ├── kyu5 ├── DoubleCola.java ├── FactorialDecomposition.java ├── HumanReadableTime.java ├── MergeIn2048.java ├── Scramblies.java ├── SimplePigLatin.java ├── SnakesLadders.java └── WhatsThePerfectPowerAnyway.java ├── kyu6 ├── AreTheyTheSame.java ├── BreakCamelCase.java ├── BuyingACar.java ├── CamelCaseMethod.java ├── ConsecutiveFib.java ├── ConvertStringToCamelCase.java ├── DigitalRoot.java ├── Dubstep.java ├── DuplicateEncoder.java ├── EncryptThis.java ├── EnoughIsEnough.java ├── ExtractFileName.java ├── FindOdd.java ├── FindUniqueNumber.java ├── GiveMeADiamond.java ├── IsANumberPrime.java ├── MultiplesOf3And5.java ├── PersistentBugger.java ├── ReverseWords.java ├── TakeATenMinuteWalk.java ├── VasyaClerk.java ├── WhereIsMyParent.java └── WhoLikesIt.java └── kyu7 ├── ColouredTriangles.java ├── HalvingSum.java ├── JadenCasingStrings.java ├── LargestFiveDigit.java ├── MultiplesOfN.java ├── PrinterErrors.java ├── SplitInParts.java └── SumOfNumbers.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | 26 | /.idea/ 27 | /.git 28 | /out -------------------------------------------------------------------------------- /CodeWars.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeWars 2 | 3 | ![alt text](https://www.codewars.com/users/whiskels/badges/micro) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/c26fc725195845d2ac82845bb39c653c)](https://app.codacy.com/manual/whiskels/CodeWars?utm_source=github.com&utm_medium=referral&utm_content=whiskels/CodeWars&utm_campaign=Badge_Grade_Dashboard) 4 | 5 | [Profile](https://www.codewars.com/users/whiskels) 6 | 7 | Contains katas solved in Java. Each solved kata consists of javadoc with info about it, code and (in some katas) JUnit tests in same file. 8 | This structure is used in order to facilitate analysis of solution. 9 | 10 | ## Katas: 11 | ### 3 kyu: 12 | - [Battleship field validator](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu3/BattleField.java) 13 | - [Rail Fence Cipher](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu3/RailFenceCipher.java) 14 | - [Make a spiral](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu3/MakeASpiral.java) 15 | - [The lift](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu3/Dinglemouse.java) 16 | ### 4 kyu: 17 | - [Boggle World Checker](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/Boggle.java) 18 | - [Conway's Game of Life - Unlimited Edition](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/ConwayLife.java) 19 | - [How many numbers III?](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/HowManyNumbers.java) 20 | - [Pyramid Slide Down](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/LongestSlideDown.java) 21 | - [Recover a secret string from random triplets](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/SecretDetective.java) 22 | - [Snail sort](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/SnailSort.java) 23 | - [Strip comments](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/StripComments.java) 24 | - [Sudoku solution validator](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/SudokuSolutionValidator.java) 25 | - [Human readable duration format](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/TimeFormatter.java) 26 | - [Most frequently used words in a text](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/TopWords.java) 27 | - [Strings Mix](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu4/StringsMix.java) 28 | ### 5 kyu: 29 | - [Factorial decomposition](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/FactorialDecomposition.java) 30 | - [Human readable time](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/HumanReadableTime.java) 31 | - [Merge in 2048](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/MergeIn2048.java) 32 | - [Simple pig latin](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/SimplePigLatin.java) 33 | - [Snakes and Ladders](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/SnakesLadders.java) 34 | - [What's the Perfect Power anyway?](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/WhatsThePerfectPowerAnyway.java) 35 | - [Scramblies](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/Scramblies.java) 36 | - [Double cola](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu5/DoubleCola.java) 37 | ### 6 kyu: 38 | - [Are they the "same"?](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/AreTheyTheSame.java) 39 | - [Break camelCase](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/BreakCamelCase.java) 40 | - [Buying a car](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/BuyingACar.java) 41 | - [CamelCase method](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/CamelCaseMethod.java) 42 | - [Product of consecutive Fib numbers](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/ConsecutiveFib.java) 43 | - [Convert string to camel case](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/ConvertStringToCamelCase.java) 44 | - [Digital root](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/DigitalRoot.java) 45 | - [Dubstep](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/Dubstep.java) 46 | - [Duplicate encoder](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/DuplicateEncoder.java) 47 | - [Encrypt this](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/EncryptThis.java) 48 | - [Enough is enough](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/EnoughIsEnough.java) 49 | - [Extract file name](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/ExtractFileName.java) 50 | - [Find the odd int](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/FindOdd.java) 51 | - [Find the unique number](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/FindUniqueNumber.java) 52 | - [Give me a Diamond](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/GiveMeADiamond.java) 53 | - [Is a number prime?](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/IsANumberPrime.java) 54 | - [Multiples of 3 or 5](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/MultiplesOf3And5.java) 55 | - [Stop gninnipS My sdroW!](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/ReverseWords.java) 56 | - [Take a ten minute walk](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/TakeATenMinuteWalk.java) 57 | - [Vasya clerk](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/VasyaClerk.java) 58 | - [Where is my parent](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/WhereIsMyParent.java) 59 | - [Who likes it](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/WhoLikesIt.java) 60 | - [Persistent bugger](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu6/PersistentBugger.java) 61 | ### 7 kyu: 62 | - [Halving sum](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu7/HalvingSum.java) 63 | - [Jaden case strings](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu7/JadenCasingStrings.java) 64 | - [Largest five digit](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu7/LargestFiveDigit.java) 65 | - [Multiples of N](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu7/MultiplesOfN.java) 66 | - [Printer errors](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu7/PrinterErrors.java) 67 | - [Split in parts](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu7/SplitInParts.java) 68 | - [Sum of numbers](https://github.com/whiskels/CodeWars/blob/master/src/main/java/kyu7/SumOfNumbers.java) 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/kyu3/BattleField.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu3; 2 | 3 | /** 4 | * 3 kyu - Battleship field validator 5 | * 6 | * https://www.codewars.com/kata/52bb6539a4cf1b12d90005b7/java 7 | * 8 | * Details: 9 | * 10 | * Write a method that takes a field for well-known board game "Battleship" as an argument and 11 | * returns true if it has a valid disposition of ships, false otherwise. Argument is guaranteed 12 | * to be 10*10 two-dimension array. Elements in the array are numbers, 0 if the cell is free and 13 | * 1 if occupied by ship. 14 | * 15 | * Battleship (also Battleships or Sea Battle) is a guessing game for two players. Each player has 16 | * a 10x10 grid containing several "ships" and objective is to destroy enemy's forces by targetting 17 | * individual cells on his field.mThe ship occupies one or more cells in the grid. Size and number 18 | * of ships may differ from version to version. 19 | * 20 | * In this kata we will use Soviet/Russian version of the game. 21 | * 22 | * Before the game begins, players set up the board and place the ships accordingly to the 23 | * following rules: 24 | * 25 | * - There must be single battleship (size of 4 cells), 2 cruisers (size 3), 3 destroyers 26 | * (size 2) and 4 submarines 27 | * (size 1). Any additional ships are not allowed, as well as missing ships. 28 | * - Each ship must be a straight line, except for submarines, which are just single cell. 29 | * - The ship cannot overlap or be in contact with any other ship, neither by edge nor by corner. 30 | */ 31 | 32 | public class BattleField { 33 | private final int[][] field; 34 | private boolean[][] checkedCells; 35 | private int submarines; 36 | private int destroyers; 37 | private int cruiserShips; 38 | private int battleShips; 39 | 40 | /* Main kata method */ 41 | public static boolean fieldValidator(int[][] field) { 42 | BattleField bf = new BattleField(field); 43 | 44 | for (int i = 0; i < field.length; i++) { 45 | for (int j = 0; j < field[i].length; j++) { 46 | if (!bf.checkedCells[i][j]) { 47 | if (bf.field[i][j] == 1 && !bf.checkPart(i, j)) { 48 | return false; 49 | } else { 50 | bf.checkedCells[i][j] = true; 51 | } 52 | } 53 | } 54 | } 55 | 56 | return bf.submarines == 0 && bf.cruiserShips == 0 && bf.destroyers == 0 && bf.battleShips == 0; 57 | } 58 | 59 | /* Private constructor is called inside fieldValidator */ 60 | private BattleField(int[][] field) { 61 | this.field = field; 62 | submarines = 4; 63 | destroyers = 3; 64 | cruiserShips = 2; 65 | battleShips = 1; 66 | checkedCells = new boolean[field.length][field[0].length]; 67 | } 68 | 69 | /* Checks ship part - counts ship parts in nearest cells and finds ship if found 1 neighbor */ 70 | private boolean checkPart(int y, int x) { 71 | System.out.println(String.format("Ship part found at %d %d", y, x)); 72 | 73 | final int neighbors = countNeighbors(y, x); 74 | 75 | if (neighbors > 2 || (neighbors == 1 && !findShip(y, x))) { 76 | return false; 77 | } else if (neighbors == 0) { 78 | submarines--; 79 | checkedCells[y][x] = true; 80 | System.out.println(String.format("\t- submarine count: %d", submarines)); 81 | } 82 | 83 | return true; 84 | } 85 | 86 | /* Counts ship parts nearby */ 87 | private int countNeighbors(int y, int x) { 88 | int neighbors = 0; 89 | 90 | for (int i = y - 1; i <= y + 1; i++) { 91 | for (int j = x - 1; j <= x + 1; j++) { 92 | if (!(i == y && j == x) && isValidCoodrinates(i, j)) { 93 | if (field[i][j] == 1) { 94 | neighbors++; 95 | } else { 96 | checkedCells[i][j] = true; 97 | } 98 | } 99 | } 100 | } 101 | System.out.println(String.format("\t- neighbor count: %d", neighbors)); 102 | return neighbors; 103 | } 104 | 105 | /* Checks that loop coordinates are inside game field */ 106 | private boolean isValidCoodrinates(int y, int x) { 107 | return y >= 0 && 108 | x >= 0 && 109 | y < field.length && 110 | x < field[y].length; 111 | } 112 | 113 | /* Finds all ship parts */ 114 | private boolean findShip(int y, int x) { 115 | System.out.println("\t- estimating ship size"); 116 | int size = 1; 117 | 118 | int dX = 0, dY = 0, currentY = -1, currentX = -1; 119 | 120 | // Find ship's direction 121 | for (int i = y - 1; i <= y + 1; i++) { 122 | for (int j = x - 1; j <= x + 1; j++) { 123 | if (isValidCoodrinates(i, j)) { 124 | if (i == y && j == x) { 125 | continue; 126 | } else if (field[i][j] == 1) { 127 | if (isDiagonalNeighborPresent(i, j)) return false; 128 | dY = i - y; 129 | dX = j - x; 130 | currentY = i + dY; 131 | currentX = j + dX; 132 | size++; 133 | System.out.println(String.format( 134 | "\t- found ship part at %d %d. Direction is %d %d", i, j, dY, dX)); 135 | break; 136 | } else { 137 | checkedCells[i][j] = true; 138 | } 139 | } 140 | } 141 | } 142 | 143 | // If direction found - calculate ship size 144 | if (currentX != -1) { 145 | for (; currentX >= 0 && 146 | currentX < field[0].length && 147 | currentY >= 0 && 148 | currentY < field.length; currentX += dX, currentY += dY) { 149 | if (field[currentY][currentX] == 1) { 150 | if (isDiagonalNeighborPresent(currentY, currentX)) { 151 | return false; 152 | } 153 | size++; 154 | } else { 155 | if (size > 4) { 156 | return false; 157 | } 158 | break; 159 | } 160 | } 161 | } 162 | 163 | removeShipBySize(currentY - dY, currentX - dX, dY, dX, size); 164 | 165 | return submarines >= 0 && cruiserShips >= 0 && destroyers >= 0 && battleShips >= 0; 166 | } 167 | 168 | /* Checks if current ship part has any ship parts in diagonal neighbor cells */ 169 | private boolean isDiagonalNeighborPresent(int y, int x) { 170 | for (int i = y - 1; i <= y + 1; i++) { 171 | for (int j = x - 1; j <= x + 1; j++) { 172 | if (i != y && j != x && isValidCoodrinates(i, j)) { 173 | if (field[i][j] == 1) { 174 | return true; 175 | } else { 176 | checkedCells[i][j] = true; 177 | } 178 | } 179 | } 180 | } 181 | System.out.println(String.format("\t- no diagonal neighbors for %d %d", y, x)); 182 | return false; 183 | } 184 | 185 | /* Decrements ship counter based on ship size */ 186 | private void removeShipBySize(int currentY, int currentX, int dY, int dX, int size) { 187 | int y = currentY; 188 | int x = currentX; 189 | int sizeCopy = size; 190 | 191 | System.out.println(String.format("\t- ship size: %d", size)); 192 | 193 | if (sizeCopy == 2) { 194 | destroyers--; 195 | System.out.println(String.format("\t- Destroyer count: %d", destroyers)); 196 | } else if (sizeCopy == 3) { 197 | cruiserShips--; 198 | System.out.println(String.format("\t- Cruiser count: %d", cruiserShips)); 199 | } else if (sizeCopy == 4) { 200 | battleShips--; 201 | System.out.println(String.format("\t- Battleship count: %d", battleShips)); 202 | } 203 | 204 | while (size != 0) { 205 | checkedCells[currentY][x] = true; 206 | x -= dX; 207 | y -= dY; 208 | sizeCopy--; 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/main/java/kyu3/Dinglemouse.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu3; 2 | 3 | /** 4 | * 3 kyu - The lift 5 | * 6 | * https://www.codewars.com/kata/58905bfa1decb981da00009e 7 | * 8 | * Details: 9 | * 10 | * Synopsis 11 | * 12 | * A multi-floor building has a Lift in it. 13 | * 14 | * People are queued on different floors waiting for the Lift. 15 | * 16 | * Some people want to go up. Some people want to go down. 17 | * 18 | * The floor they want to go to is represented by a number 19 | * (i.e. when they enter the Lift this is the button they will press) 20 | * 21 | * Rules 22 | * Lift Rules 23 | * 24 | * The Lift only goes up or down! 25 | * Each floor has both UP and DOWN Lift-call buttons (except top and ground floors which have 26 | * only DOWN and UP respectively) 27 | * The Lift never changes direction until there are no more people wanting to get on/off in the 28 | * direction it is already travelling 29 | * When empty the Lift tries to be smart. For example, 30 | * If it was going up then it may continue up to collect the highest floor person wanting 31 | * to go down 32 | * If it was going down then it may continue down to collect the lowest floor person 33 | * wanting to go up 34 | * The Lift has a maximum capacity of people 35 | * When called, the Lift will stop at a floor even if it is full, although unless somebody gets 36 | * off nobody else can get on! 37 | * If the lift is empty, and no people are waiting, then it will return to the ground floor 38 | * 39 | * People Rules 40 | * 41 | * People are in "queues" that represent their order of arrival to wait for the Lift 42 | * All people can press the UP/DOWN Lift-call buttons 43 | * Only people going the same direction as the Lift may enter it 44 | * Entry is according to the "queue" order, but those unable to enter do not block those behind 45 | * them that can 46 | * If a person is unable to enter a full Lift, they will press the UP/DOWN Lift-call button 47 | * again after it has departed without them 48 | * 49 | * Kata Task 50 | * 51 | * Get all the people to the floors they want to go to while obeying the Lift rules and the 52 | * People rules 53 | * Return a list of all floors that the Lift stopped at (in the order visited!) 54 | * 55 | * NOTE: The Lift always starts on the ground floor (and people waiting on the ground floor may 56 | * enter immediately) 57 | */ 58 | 59 | import java.util.*; 60 | import java.util.stream.IntStream; 61 | 62 | public class Dinglemouse { 63 | private final int capacity; // Lift capacity 64 | private final Map queues; // Current queues 65 | private boolean isFinished; // Is everyone at desired floor 66 | private Direction direction; // Current travel direction 67 | private List peopleInside; // List of people inside lift 68 | private List visitedFloors; // Floors that lift has visited 69 | private int currentFloor, limitFloor; // Floor variables (current, max next) 70 | 71 | private static enum Direction {UP, DOWN;} 72 | 73 | /* Additional class, representing each passenger standing in a queue */ 74 | class Passenger { 75 | private final int desiredFloor; 76 | private final Direction direction; 77 | 78 | public Passenger(int startFloor, int desiredFloor) { 79 | this.desiredFloor = desiredFloor; 80 | this.direction = desiredFloor > startFloor ? Direction.UP : Direction.DOWN; 81 | } 82 | 83 | public final String toString() { 84 | return String.format("From floor to %d (%s)", desiredFloor, direction); 85 | } 86 | } 87 | 88 | /* Constructor is used to avoid using static members; */ 89 | private Dinglemouse(int[][] queues, final int capacity) { 90 | this.capacity = capacity; 91 | this.queues = new HashMap<>(queues.length); 92 | fillQueues(queues); 93 | peopleInside = new ArrayList<>(capacity); 94 | direction = Direction.UP; 95 | currentFloor = 0; 96 | visitedFloors = new ArrayList<>(); 97 | isFinished = false; 98 | 99 | printQueue(); // Print initial state 100 | msg(String.format("Lift:\n\t" + 101 | "Lift capacity: %d\n\t" + 102 | "Total number of floors: %d", capacity, queues.length)); 103 | } 104 | 105 | // Starting point 106 | public static int[] theLift(final int[][] queues, final int capacity) { 107 | Dinglemouse lift = new Dinglemouse(queues, capacity); 108 | lift.work(); 109 | return lift.getVisitedFloors(); 110 | } 111 | 112 | /* Prints messages */ 113 | public static void msg(String line) { 114 | System.out.println(line); 115 | } 116 | 117 | /* Used to fill queues map with initial values */ 118 | private void fillQueues(int[][] queues) { 119 | for (int i = 0; i < queues.length; i++) { 120 | this.queues.put(i, new ArrayList<>(queues[i].length)); 121 | for (int j = 0; j < queues[i].length; j++) { 122 | this.queues.get(i).add(new Passenger(i, queues[i][j])); 123 | } 124 | } 125 | } 126 | 127 | /* Main method with lift logic */ 128 | private void work() { 129 | visitedFloors.add(currentFloor); 130 | recalculateLimitFloor(); 131 | 132 | while (!isFinished) { 133 | if (checkFloor()) { 134 | msg(String.format("Stopped at floor %d", currentFloor)); 135 | dropPassengers(); 136 | pickPassengers(); 137 | 138 | if (visitedFloors.get(visitedFloors.size() - 1) != currentFloor) { 139 | visitedFloors.add(currentFloor); 140 | } 141 | } else { 142 | msg(String.format("Skipping floor %d", currentFloor)); 143 | } 144 | 145 | if (currentFloor == limitFloor) { 146 | msg("Reached max floor"); 147 | switchDirection(); 148 | } else { 149 | changeFloor(); 150 | } 151 | isFinished = isNotFinished(); 152 | } 153 | 154 | msg("Everyone is on desired floors, returning to ground floor"); 155 | currentFloor = 0; 156 | 157 | if (visitedFloors.get(visitedFloors.size() - 1) != 0) { 158 | visitedFloors.add(0); 159 | } 160 | } 161 | 162 | /* Proceeds to next floor */ 163 | private void changeFloor() { 164 | currentFloor += direction == Direction.UP ? 1 : -1; 165 | } 166 | 167 | /* Checks if current floor is target floor for any of the passengers or anyone can enter lift */ 168 | private boolean checkFloor() { 169 | boolean isAnyoneDesired = peopleInside.size() == 0 ? false : peopleInside.stream() 170 | .anyMatch(passenger -> passenger.desiredFloor == currentFloor); 171 | 172 | boolean isAnyoneToEnter = queues.get(currentFloor).size() == 0 ? false : queues.get(currentFloor).stream() 173 | .anyMatch(passenger -> isSameDirection((Passenger) passenger)); 174 | 175 | return isAnyoneDesired || isAnyoneToEnter; 176 | } 177 | 178 | /* Inverts lift's direction */ 179 | private void switchDirection() { 180 | direction = direction == Direction.UP ? Direction.DOWN : Direction.UP; 181 | recalculateLimitFloor(); 182 | } 183 | 184 | /* Updates limit floor */ 185 | private void recalculateLimitFloor() { 186 | limitFloor = direction == Direction.UP ? getMaxNextFloor() : getMinNextFloor(); 187 | msg(String.format("Max floor %d", limitFloor)); 188 | } 189 | 190 | private int getMaxNextFloor() { 191 | return Math.max(maxNextFloorForPassengers(), maxNextFloorWithPassengers()); 192 | } 193 | 194 | private int getMinNextFloor() { 195 | return Math.min(minNextFloorForPassengers(), minNextFloorWithPassengers()); 196 | } 197 | 198 | /* Calculates maximum floor with passengers in queue */ 199 | private int maxNextFloorWithPassengers() { 200 | for (int i = queues.size() - 1; i > currentFloor; i--) { 201 | if (queues.get(i).size() != 0) { 202 | return i; 203 | } 204 | } 205 | return currentFloor; 206 | } 207 | 208 | /* Calculates minimum floor with passengers in queue */ 209 | private int minNextFloorWithPassengers() { 210 | for (int i = 0; i < currentFloor; i++) { 211 | if (queues.get(i).size() != 0) { 212 | return i; 213 | } 214 | } 215 | return currentFloor; 216 | } 217 | 218 | /* Calculates maximum floor for passengers inside lift */ 219 | private int maxNextFloorForPassengers() { 220 | return peopleInside.stream() 221 | .mapToInt(passenger -> passenger.desiredFloor) 222 | .max() 223 | .orElse(currentFloor); 224 | } 225 | 226 | /* Calculates minimum floor for passengers inside lift */ 227 | private int minNextFloorForPassengers() { 228 | return peopleInside.stream() 229 | .mapToInt(passenger -> passenger.desiredFloor) 230 | .min() 231 | .orElse(currentFloor); 232 | } 233 | 234 | /* Adds passengers from current floor to lift */ 235 | private void pickPassengers() { 236 | final List floor = queues.get(currentFloor); 237 | if (floor.size() != 0) { 238 | msg(String.format("Trying to add passengers at floor %d, current direction is %s", currentFloor, direction)); 239 | for (int i = 0; i < floor.size(); i++) { 240 | if (countPassengersInside() == capacity) { 241 | msg("Stopped adding new passengers"); 242 | break; 243 | } 244 | 245 | Passenger current = (Passenger) floor.get(i); 246 | 247 | if (isSameDirection(current)) { 248 | peopleInside.add(current); 249 | floor.set(i, null); 250 | msg(String.format("Passenger entered lift: %s", current.toString())); 251 | recalculateLimitFloor(); 252 | } else { 253 | msg(String.format("Skipped passenger: %s", current.toString())); 254 | } 255 | } 256 | floor.removeIf(Objects::isNull); 257 | } else { 258 | msg(String.format("Floor %d is empty, current direction is %s", currentFloor, direction)); 259 | } 260 | } 261 | 262 | /* Removes passengers from lift if their desired floor matches current floor */ 263 | private void dropPassengers() { 264 | if (countPassengersInside() != 0) { 265 | IntStream.range(0, countPassengersInside()) 266 | .filter(i -> peopleInside.get(i).desiredFloor == currentFloor) 267 | .forEach(i -> { 268 | final Passenger passenger = peopleInside.get(i); 269 | msg(String.format("Passenger left the lift at floor %d: %s", currentFloor, passenger.toString())); 270 | peopleInside.set(i, null); 271 | }); 272 | peopleInside.removeIf(Objects::isNull); 273 | } else { 274 | msg("No passengers inside - nobody to leave"); 275 | } 276 | } 277 | 278 | /* Checks if everybody is on the desired floor */ 279 | private boolean isNotFinished() { 280 | return countPassengersInside() == 0 && queues.entrySet().stream() 281 | .flatMap(floor -> floor.getValue().stream()) 282 | .count() == 0; 283 | } 284 | 285 | /* Checks if passenger's direction matches current lift's direction */ 286 | private boolean isSameDirection(Passenger passenger) { 287 | return passenger.direction == direction; 288 | } 289 | 290 | /* Counts passengers inside lift */ 291 | private int countPassengersInside() { 292 | return (int) peopleInside.stream() 293 | .filter(p -> p != null) 294 | .count(); 295 | } 296 | 297 | /* Converts visited floors to array */ 298 | private int[] getVisitedFloors() { 299 | int[] result = new int[visitedFloors.size()]; 300 | for (int i = 0; i < visitedFloors.size(); i++) { 301 | result[i] = visitedFloors.get(i); 302 | System.out.print(result[i] + " "); 303 | } 304 | return result; 305 | } 306 | 307 | /* Prints queue state */ 308 | public void printQueue() { 309 | for (int i = this.queues.size() - 1; i >= 0; i--) { 310 | System.out.print(String.format("%d |", i)); 311 | if (this.queues.get(i).size() != 0) { 312 | for (int j = this.queues.get(i).size() - 1; j >= 0; j--) { 313 | Passenger passenger = (Passenger) this.queues.get(i).get(j); 314 | System.out.println(String.format(" %s", passenger.toString())); 315 | } 316 | } else { 317 | System.out.println(" Nobody"); 318 | } 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /src/main/java/kyu3/MakeASpiral.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu3; 2 | 3 | /** 4 | * 3 kyu - Make a spiral 5 | * 6 | * https://www.codewars.com/kata/534e01fbbb17187c7e0000c6 7 | * 8 | * Details: 9 | * 10 | * Your task, is to create a NxN spiral with a given size. 11 | */ 12 | 13 | import org.junit.Test; 14 | 15 | import java.util.Arrays; 16 | 17 | import static org.junit.Assert.assertArrayEquals; 18 | 19 | public class MakeASpiral { 20 | public static int[][] spiralize(int size) { 21 | if (size < 5) { 22 | return null; 23 | } 24 | 25 | return spiralize(new int[size][size]); 26 | } 27 | 28 | public static int[][] spiralize(int[][] arr) { 29 | int[][] fill = fill(arr); 30 | 31 | final int height = fill.length; 32 | final int width = fill[0].length; 33 | int lastY = height / 2; 34 | int lastX = width % 2 == 0 ? width / 2 - 1 : width / 2; 35 | 36 | // Extra variants 37 | if (height == 5) { 38 | lastX = 1; 39 | lastY = 3; 40 | } else if ((height - 5) % 4 == 0) { 41 | lastX--; 42 | lastY++; 43 | } 44 | 45 | int y = 1, x = 0, dirX = 1, dirY = 0, i = 0; 46 | int leftBorder = 0, rightBorder = width - 1; 47 | int upperBorder = 0, lowerBorder = height - 1; 48 | 49 | while (true) { 50 | if (x == rightBorder && y == upperBorder + 1) { 51 | x--; 52 | y++; 53 | dirX = 0; 54 | dirY = 1; 55 | upperBorder += 2; 56 | } else if (x == leftBorder && y == lowerBorder - 1) { 57 | x++; 58 | y--; 59 | dirX = 0; 60 | dirY = -1; 61 | lowerBorder -= 2; 62 | } else if (y == lowerBorder && x == rightBorder - 1) { 63 | y--; 64 | x--; 65 | dirX = -1; 66 | dirY = 0; 67 | rightBorder -= 2; 68 | } else if (y == upperBorder && x == leftBorder + 1) { 69 | y++; 70 | x++; 71 | dirX = 1; 72 | dirY = 0; 73 | leftBorder += 2; 74 | } 75 | fill[y][x] = 0; 76 | 77 | if (y == lastY && x == lastX) { 78 | break; 79 | } 80 | 81 | x += dirX; 82 | y += dirY; 83 | i++; 84 | } 85 | 86 | return fill; 87 | } 88 | 89 | public static int[][] fill(int[][] arr) { 90 | for (int[] row : arr) { 91 | Arrays.fill(row, 1); 92 | } 93 | return arr; 94 | } 95 | 96 | @Test 97 | public void test5() { 98 | assertArrayEquals( 99 | new int[][]{ 100 | {1, 1, 1, 1, 1}, 101 | {0, 0, 0, 0, 1}, 102 | {1, 1, 1, 0, 1}, 103 | {1, 0, 0, 0, 1}, 104 | {1, 1, 1, 1, 1} 105 | }, 106 | spiralize(5)); 107 | } 108 | 109 | @Test 110 | public void test8() { 111 | assertArrayEquals( 112 | new int[][]{ 113 | {1, 1, 1, 1, 1, 1, 1, 1}, 114 | {0, 0, 0, 0, 0, 0, 0, 1}, 115 | {1, 1, 1, 1, 1, 1, 0, 1}, 116 | {1, 0, 0, 0, 0, 1, 0, 1}, 117 | {1, 0, 1, 0, 0, 1, 0, 1}, 118 | {1, 0, 1, 1, 1, 1, 0, 1}, 119 | {1, 0, 0, 0, 0, 0, 0, 1}, 120 | {1, 1, 1, 1, 1, 1, 1, 1}, 121 | }, 122 | spiralize(8)); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/kyu3/RailFenceCipher.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu3; 2 | 3 | /** 4 | * 3 kyu - Rail Fence Cipher: Encoding and Decoding 5 | * 6 | * https://www.codewars.com/kata/58c5577d61aefcf3ff000081 7 | * 8 | * Details: 9 | * 10 | * Create two functions to encode and then decode a string using the Rail Fence Cipher. This cipher 11 | * is used to encode a string by placing each character successively in a diagonal along a set of 12 | * "rails". First start off moving diagonally and down. When you reach the bottom, reverse 13 | * direction and move diagonally and up until you reach the top rail. 14 | * Continue until you reach the end of the string. Each "rail" is then read left to right to derive 15 | * the encoded string. 16 | * 17 | * For example, the string "WEAREDISCOVEREDFLEEATONCE" could be represented in a three rail system 18 | * as follows: 19 | * 20 | * W E C R L T E 21 | * E R D S O E E F E A O C 22 | * A I V D E N 23 | * 24 | * The encoded string would be: 25 | * 26 | * WECRLTEERDSOEEFEAOCAIVDEN 27 | * 28 | * Write a function/method that takes 2 arguments, a string and the number of rails, and returns 29 | * the ENCODED string. 30 | * 31 | * Write a second function/method that takes 2 arguments, an encoded string and the number of 32 | * rails, and returns the DECODED string. 33 | * 34 | * For both encoding and decoding, assume number of rails >= 2 and that passing an empty string 35 | * will return an empty string. 36 | * 37 | * Note that the example above excludes the punctuation and spaces just for simplicity. There are, 38 | * however, tests that include punctuation. Don't filter out punctuation as they are a part of the 39 | * string. 40 | */ 41 | 42 | import org.junit.jupiter.api.Test; 43 | 44 | import java.util.ArrayList; 45 | 46 | import static org.junit.jupiter.api.Assertions.assertEquals; 47 | 48 | public class RailFenceCipher { 49 | 50 | public static String encode(String s, int n) { 51 | if (s == null || s.length() == 0) { 52 | return ""; 53 | } 54 | 55 | ArrayList sbList = new ArrayList<>(n); 56 | 57 | for (int i = 0; i < n; i++) { 58 | sbList.add(new StringBuilder()); 59 | } 60 | 61 | for (int i = 0; i < s.length(); i++) { 62 | int j = i % ((n - 1) * 2); 63 | j = j >= n ? n - (j % n) - 2 : j % n; 64 | sbList.get(j).append(s.charAt(i)); 65 | } 66 | 67 | StringBuilder result = new StringBuilder(); 68 | 69 | for (StringBuilder sb : sbList) { 70 | result.append(sb); 71 | } 72 | 73 | return new String(result); 74 | } 75 | 76 | public static String decode(String s, int n) { 77 | if (s == null || s.length() == 0) { 78 | return ""; 79 | } 80 | 81 | int currRow = 0; 82 | int rowDirection = 1; 83 | int currIndex = 0; 84 | ArrayList chars = new ArrayList<>(s.length()); 85 | 86 | for (int i = 0; i < s.length(); i++) { 87 | chars.add(i, null); 88 | } 89 | 90 | for (int i = 0; i < s.length(); i++) { 91 | chars.set(currIndex, s.charAt(i)); 92 | 93 | currIndex += (n - 1) * 2; 94 | 95 | if (currRow > 0 && currRow < n - 1) { 96 | int addIndex = currIndex - (currRow * 2); 97 | 98 | if (addIndex < s.length() && (i + 1 < s.length())) { 99 | chars.set(addIndex, s.charAt(++i)); 100 | } 101 | } 102 | 103 | if (currIndex >= s.length()) { 104 | if (currRow == 0) rowDirection = 1; 105 | if (currRow == n - 1) rowDirection = -1; 106 | 107 | currRow += rowDirection; 108 | currIndex = currRow; 109 | } 110 | } 111 | 112 | final StringBuilder sb = new StringBuilder(); 113 | 114 | for (Character c : chars) { 115 | sb.append(c); 116 | } 117 | 118 | return new String(sb); 119 | } 120 | 121 | @Test 122 | public void encodeSampleTests() { 123 | String[][] encodes = {{"WEAREDISCOVEREDFLEEATONCE", "WECRLTEERDSOEEFEAOCAIVDEN"}, // 3 rails 124 | {"Hello, World!", "Hoo!el,Wrdl l"}, // 3 rails 125 | {"Hello, World!", "H !e,Wdloollr"}, // 4 rails 126 | {"", ""} // 3 rails (even if...) 127 | }; 128 | int[] rails = {3, 3, 4, 3}; 129 | for (int i = 0; i < encodes.length; i++) { 130 | assertEquals(encodes[i][1], RailFenceCipher.encode(encodes[i][0], rails[i])); 131 | } 132 | } 133 | 134 | @Test 135 | public void decodeSampleTests() { 136 | String[][] decodes = {{"WECRLTEERDSOEEFEAOCAIVDEN", "WEAREDISCOVEREDFLEEATONCE"}, // 3 rails 137 | {"H !e,Wdloollr", "Hello, World!"}, // 4 rails 138 | {"", ""} // 3 rails (even if...) 139 | }; 140 | int[] rails = {3, 4, 3}; 141 | for (int i=0 ; i < decodes.length ; i++) { 142 | assertEquals(decodes[i][1], RailFenceCipher.decode(decodes[i][0], rails[i])); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/kyu4/Boggle.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Boggle World Checker 5 | *

6 | * https://www.codewars.com/kata/57680d0128ed87c94f000bfd/ 7 | *

8 | * Details: 9 | *

10 | * Write a function that determines whether a string is a valid guess in a Boggle board, as per the 11 | * rules of Boggle. 12 | *

13 | * A Boggle board is a 2D array of individual characters, e.g.: 14 | *

15 | * [ ['I','L','A','W'], 16 | * ['B','N','G','E'], 17 | * ['I','U','A','O'], 18 | * ['A','S','R','L'] ] 19 | *

20 | * Valid guesses are strings which can be formed by connecting adjacent cells (horizontally, 21 | * vertically, or diagonally) without re-using any previously used cells. 22 | *

23 | * For example, in the above board "BINGO", "LINGO", and "ILNBIA" would all be valid guesses, while 24 | * "BUNGIE", "BINS", and "SINUS" would not. 25 | *

26 | * Your function should take two arguments (a 2D array and a string) and return true or false 27 | * depending on whether the string is found in the array as per Boggle rules. 28 | *

29 | * Test cases will provide various array and string sizes (squared arrays up to 150x150 and strings 30 | * up to 150 uppercase letters). You do not have to check whether the string is a real word or not, 31 | * only if it's a valid guess. 32 | */ 33 | 34 | public class Boggle { 35 | private final char[][] board; 36 | private final String word; 37 | 38 | public Boggle(final char[][] board, final String word) { 39 | this.board = board; 40 | this.word = word; 41 | } 42 | 43 | public boolean check() { 44 | if (word == null || word.isEmpty()) { 45 | return false; 46 | } 47 | int[][] usedCoords = new int[board.length][board[0].length]; 48 | 49 | for (int y = 0; y < board.length; y++) { 50 | for (int x = 0; x < board[y].length; x++) { 51 | if (board[y][x] == word.charAt(0) && isMatch(x, y, 1, usedCoords)) 52 | return true; 53 | } 54 | } 55 | return false; 56 | } 57 | 58 | private boolean isMatch(int prevX, int prevY, int currentIndex, int[][] usedCoords) { 59 | if (currentIndex >= word.length()) return true; 60 | 61 | char currentChar = word.charAt(currentIndex); 62 | usedCoords[prevY][prevX] = 1; 63 | 64 | for (int y = prevY - 1; y <= prevY + 1; y++) { 65 | for (int x = prevX - 1; x <= prevX + 1; x++) { 66 | if (y >= 0 && x >= 0 && y < board.length && x < board[y].length) { 67 | if (board[y][x] == currentChar && usedCoords[y][x] != 1 && 68 | isMatch(x, y, currentIndex + 1, usedCoords)) 69 | return true; 70 | } 71 | } 72 | } 73 | 74 | usedCoords[prevY][prevX] = 0; 75 | 76 | return false; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/kyu4/ConwayLife.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Conway's Game of Life - Unlimited Edition 5 | *

6 | * https://www.codewars.com/kata/52423db9add6f6fc39000354 7 | *

8 | * Given a 2D array and a number of generations, compute n timesteps of Conway's Game of Life. 9 | *

10 | * The rules of the game are: 11 | *

12 | * Any live cell with fewer than two live neighbours dies, as if caused by underpopulation. 13 | * Any live cell with more than three live neighbours dies, as if by overcrowding. 14 | * Any live cell with two or three live neighbours lives on to the next generation. 15 | * Any dead cell with exactly three live neighbours becomes a live cell. 16 | *

17 | * Each cell's neighborhood is the 8 cells immediately around it (i.e. Moore Neighborhood). 18 | * The universe is infinite in both the x and y dimensions and all cells are initially dead - 19 | * except for those specified in the arguments. The return value should be a 2d array cropped 20 | * around all of the living cells. (If there are no living cells, then return [[]].) 21 | */ 22 | 23 | public class ConwayLife { 24 | private static int height; 25 | private static int width; 26 | 27 | public static int[][] getGeneration(int[][] cells, int generations) { 28 | if (generations < 0) { 29 | return cells; 30 | } 31 | 32 | height = cells.length; 33 | width = cells[0].length; 34 | int[][] result = cells; 35 | 36 | for (int i = 0; i < generations; i++) { 37 | result = nextGeneration(result); 38 | } 39 | 40 | return result; 41 | } 42 | 43 | private static final int[][] nextGeneration(int[][] currGen) { 44 | int[][] expand = expand(currGen); 45 | int[][] nextGen = new int[height][width]; 46 | 47 | for (int y = 0; y < height; y++) { 48 | for (int x = 0; x < width; x++) { 49 | final int neighbors = countAliveNeighbors(expand, x, y); 50 | if (neighbors == 3 && expand[y][x] == 0) { 51 | nextGen[y][x] = 1; 52 | } else if ((neighbors > 3 || neighbors < 2) && expand[y][x] == 1) { 53 | nextGen[y][x] = 0; 54 | } else { 55 | nextGen[y][x] = expand[y][x]; 56 | } 57 | } 58 | } 59 | nextGen = crop(nextGen); 60 | 61 | return nextGen; 62 | } 63 | 64 | private static final int[][] expand(int[][] cells) { 65 | height += 2; 66 | width += 2; 67 | int[][] cellsExp = new int[height][width]; 68 | 69 | for (int y = 0; y < cells.length; y++) { 70 | for (int x = 0; x < cells[y].length; x++) { 71 | cellsExp[y + 1][x + 1] = cells[y][x]; 72 | } 73 | } 74 | 75 | return cellsExp; 76 | } 77 | 78 | private static final int countAliveNeighbors(int[][] cells, int currX, int currY) { 79 | int result = 0; 80 | 81 | for (int y = currY - 1; y <= currY + 1; y++) { 82 | for (int x = currX - 1; x <= currX + 1; x++) { 83 | if (y >= 0 && y < cells.length && x >= 0 && x < cells[0].length) { 84 | if (y == currY && x == currX) { 85 | continue; 86 | } 87 | if (cells[y][x] == 1) { 88 | result++; 89 | } 90 | } 91 | } 92 | } 93 | return result; 94 | } 95 | 96 | public static int[][] crop(int[][] cells) { 97 | int minY = cells.length; 98 | int minX = cells[0].length; 99 | int maxY = 0; 100 | int maxX = 0; 101 | 102 | for (int y = 0; y < cells.length; y++) { 103 | for (int x = 0; x < cells[0].length; x++) { 104 | if (cells[y][x] == 1) { 105 | maxY = y > maxY ? y : maxY; 106 | maxX = x > maxX ? x : maxX; 107 | minY = y < minY ? y : minY; 108 | minX = x < minX ? x : minX; 109 | } 110 | } 111 | } 112 | 113 | maxY++; 114 | maxX++; 115 | height = maxY - minY; 116 | width = maxX - minX; 117 | 118 | int[][] cellsCrop = new int[height][width]; 119 | for (int y = minY; y < maxY; y++) { 120 | for (int x = minX; x < maxX; x++) { 121 | cellsCrop[y - minY][x - minX] = cells[y][x]; 122 | } 123 | } 124 | 125 | return cellsCrop; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/kyu4/HowManyNumbers.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - How many numbers III? 5 | * 6 | * https://www.codewars.com/kata/5877e7d568909e5ff90017e6 7 | * 8 | * Details: 9 | * 10 | * We want to generate all the numbers of three digits where: 11 | * - the sum of their digits is equal to 10. 12 | * - their digits are in increasing order (the numbers may have two or more equal contiguous digits) 13 | * 14 | * The numbers that fulfill the two above constraints are: 118, 127, 136, 145, 226, 235, 244, 334 15 | * 16 | * Make a function that receives two arguments: 17 | * - the sum of digits value 18 | * - the desired number of digits for the numbers 19 | * 20 | * The function should output an array with three values: [1,2,3] 21 | * 1 - the total number of possible numbers 22 | * 2 - the minimum number 23 | * 3 - the maximum number 24 | */ 25 | 26 | import org.junit.jupiter.api.Test; 27 | 28 | import java.util.ArrayList; 29 | import java.util.Arrays; 30 | import java.util.List; 31 | 32 | import static org.junit.jupiter.api.Assertions.assertEquals; 33 | 34 | public class HowManyNumbers { 35 | private static long count; 36 | private static long min; 37 | private static long max; 38 | 39 | public static List findAll(final int sumDigits, final int numDigits) { 40 | count = 0; 41 | min = 0; 42 | max = 0; 43 | 44 | recursiveSearch(0L, 1, sumDigits, numDigits); 45 | 46 | ArrayList result = new ArrayList<>(); 47 | 48 | if (count > 0) { 49 | result.add(count); 50 | result.add(min); 51 | result.add(max); 52 | } 53 | 54 | return result; 55 | } 56 | 57 | private static void recursiveSearch(Long currNum, int prevDigit, int sumLeft, int digitsLeft) { 58 | if (sumLeft == 0 && digitsLeft == 0) { 59 | if (count == 0) min = currNum; 60 | min = min < currNum ? min : currNum; 61 | max = max > currNum ? max : currNum; 62 | count++; 63 | } else if (digitsLeft != 0) { 64 | for (int i = prevDigit; i < 10; i++) { 65 | recursiveSearch(10 * currNum + i, i,sumLeft - i, digitsLeft - 1); 66 | } 67 | } 68 | } 69 | 70 | 71 | /** 72 | * Though this code works it is not effective 73 | * 74 | public static List findAll(final int sumDigits, final int numDigits) { 75 | StringBuilder sb = new StringBuilder(); 76 | 77 | while (sb.length() != numDigits) { 78 | sb.append("1"); 79 | } 80 | 81 | long currentLong = Long.parseLong(sb.toString()); 82 | long lastLong = currentLong * 9; 83 | long count = 0, firstMatch = 0, lastMatch = 0; 84 | 85 | 86 | while (currentLong <= lastLong) { 87 | int currDigit, prevDigit = -1, digitSum = 0; 88 | // int currentPosition = 1; 89 | long i = currentLong; 90 | boolean isValid = true; 91 | 92 | while (i > 0) { 93 | currDigit = (int) i % 10; 94 | if (prevDigit != -1 && prevDigit < currDigit) { 95 | isValid = false; 96 | //currentLong += currentPosition * i % 10; 97 | break; 98 | } else if (digitSum > sumDigits) { 99 | isValid = false; 100 | break; 101 | } else { 102 | i /= 10; 103 | //currentPosition *= 10; 104 | digitSum += currDigit; 105 | prevDigit = currDigit; 106 | } 107 | } 108 | if (sumDigits != digitSum) { 109 | isValid = false; 110 | } 111 | 112 | if (isValid) { 113 | if (firstMatch == 0) firstMatch = currentLong; 114 | lastMatch = currentLong; 115 | count++; 116 | } 117 | currentLong++; 118 | } 119 | 120 | List result = new ArrayList<>(); 121 | if (count > 0) { 122 | result.add(count); 123 | result.add(firstMatch); 124 | result.add(lastMatch); 125 | } 126 | 127 | return result; 128 | } 129 | */ 130 | 131 | @Test 132 | public void exampleTests() { 133 | assertEquals(Arrays.asList(8L, 118L, 334L), HowManyNumbers.findAll(10, 3)); 134 | assertEquals(Arrays.asList(1L, 999L, 999L), HowManyNumbers.findAll(27, 3)); 135 | assertEquals(new ArrayList(), HowManyNumbers.findAll(84, 4)); 136 | assertEquals(Arrays.asList(123L, 116999L, 566666L), HowManyNumbers.findAll(35, 6)); 137 | } 138 | 139 | @Test 140 | public void hardTests() { 141 | assertEquals(Arrays.asList(409L, 11112999L, 44444445L), 142 | HowManyNumbers.findAll(33, 8)); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/kyu4/LongestSlideDown.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Pyramid Slide Down 5 | * 6 | * https://www.codewars.com/kata/551f23362ff852e2ab000037 7 | * 8 | * Details: 9 | * 10 | * Pyramids are amazing! Both in architectural and mathematical sense. If you have a computer, you 11 | * can mess with pyramids even if you are not in Egypt at the time. For example, let's consider the 12 | * following problem. Imagine that you have a pyramid built of numbers, like this one here: 13 | * 14 | * /3/ 15 | * \7\ 4 16 | * 2 \4\ 6 17 | * 8 5 \9\ 3 18 | * 19 | * Here comes the task... 20 | * 21 | * Let's say that the 'slide down' is the maximum sum of consecutive numbers from the top to the 22 | * bottom of the pyramid. As you can see, the longest 'slide down' is 3 + 7 + 4 + 9 = 23 23 | * 24 | * Your task is to write a function longestSlideDown (in ruby: longest_slide_down) that takes a 25 | * pyramid representation as argument and returns its' largest 'slide down'. For example, 26 | */ 27 | 28 | import static org.junit.Assert.assertEquals; 29 | import org.junit.Test; 30 | 31 | public class LongestSlideDown { 32 | public static int longestSlideDown(int[][] pyramid) { 33 | int[][] max = pyramid; 34 | 35 | for (int y = pyramid.length-2; y >= 0; y--) { 36 | for (int x = 0; x < pyramid[y].length; x++) { 37 | max[y][x] = pyramid[y][x] + Math.max(pyramid[y + 1][x], pyramid[y + 1][x + 1]); 38 | } 39 | } 40 | 41 | return max[0][0]; 42 | } 43 | 44 | /** Brute force times out 45 | public static int longestSlideDown(int[][] pyramid) { 46 | return branchSlide(pyramid, 0, 0, 0); 47 | } 48 | 49 | private static final int branchSlide(int[][] pyramid, int sum, int y, int x) { 50 | sum += pyramid[y][x]; 51 | if (++y == pyramid.length) { 52 | return sum; 53 | } else { 54 | return Math.max(branchSlide(pyramid, sum, y, x), branchSlide(pyramid, sum, y, x + 1)); 55 | } 56 | } 57 | */ 58 | 59 | @Test 60 | public void test() { 61 | int[][] test = new int[][] {{75}, 62 | {95, 64}, 63 | {17, 47, 82}, 64 | {18, 35, 87, 10}, 65 | {20, 4, 82, 47, 65}, 66 | {19, 1, 23, 75, 3, 34}, 67 | {88, 2, 77, 73, 7, 63, 67}, 68 | {99, 65, 4, 28, 6, 16, 70, 92}, 69 | {41, 41, 26, 56, 83, 40, 80, 70, 33}, 70 | {41, 48, 72, 33, 47, 32, 37, 16, 94, 29}, 71 | {53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14}, 72 | {70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57}, 73 | {91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48}, 74 | {63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31}, 75 | {4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23}, 76 | }; 77 | assertEquals(1074, LongestSlideDown.longestSlideDown(test)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/kyu4/SecretDetective.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Recover a secret string from random triplets 5 | * 6 | * https://www.codewars.com/kata/53f40dff5f9d31b813000774/train/java 7 | * 8 | * Details: 9 | * 10 | * There is a secret string which is unknown to you. Given a collection of random triplets from the string, recover the 11 | * original string. 12 | * 13 | * A triplet here is defined as a sequence of three letters such that each letter occurs somewhere before the next in 14 | * the given string. "whi" is a triplet for the string "whatisup". 15 | * 16 | * As a simplification, you may assume that no letter occurs more than once in the secret string. 17 | * 18 | * You can assume nothing about the triplets given to you other than that they are valid triplets and that they contain 19 | * sufficient information to deduce the original string. In particular, this means that the secret string will never 20 | * contain letters that do not occur in one of the triplets given to you. 21 | */ 22 | 23 | import org.junit.jupiter.api.Test; 24 | 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | import static org.junit.Assert.assertEquals; 29 | 30 | public class SecretDetective { 31 | public String recoverSecret(char[][] triplets) { 32 | List res = new ArrayList<>(); 33 | 34 | for (char[] triplet : triplets) { 35 | final char x = triplet[0]; 36 | final char y = triplet[1]; 37 | final char z = triplet[2]; 38 | 39 | if (!res.contains(x)) { 40 | res.add(0, x); 41 | } 42 | 43 | if (!res.contains(y)) { 44 | res.add(res.indexOf(x), y); 45 | } 46 | 47 | if (res.contains(y) && res.indexOf(y) < res.indexOf(x)) { 48 | final int index = res.indexOf(y); 49 | res.remove(index); 50 | res.add(res.indexOf(x) + 1, y); 51 | } 52 | 53 | if (!res.contains(z)) { 54 | res.add(res.indexOf(y), z); 55 | } 56 | 57 | if (res.contains(z) && res.indexOf(z) < res.indexOf(y)) { 58 | final int index = res.indexOf(z); 59 | res.remove(index); 60 | res.add(res.indexOf(y) + 1, z); 61 | } 62 | } 63 | 64 | final StringBuilder sb = new StringBuilder(); 65 | 66 | for (Character c : res) { 67 | sb.append(c); 68 | } 69 | 70 | return new String(sb); 71 | } 72 | 73 | 74 | /** 75 | * Test section 76 | */ 77 | 78 | @Test 79 | public void secret1() { 80 | SecretDetective detective = new SecretDetective(); 81 | char[][] triplets = { 82 | {'t','u','p'}, 83 | {'w','h','i'}, 84 | {'t','s','u'}, 85 | {'a','t','s'}, 86 | {'h','a','p'}, 87 | {'t','i','s'}, 88 | {'w','h','s'} 89 | }; 90 | assertEquals("whatisup", detective.recoverSecret(triplets)); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/kyu4/SnailSort.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Snail Sort 5 | * 6 | * https://www.codewars.com/kata/521c2db8ddc89b9b7a0000c1/ 7 | * 8 | * Details: 9 | * 10 | * Given an n x n array, return the array elements arranged from outermost elements to the middle 11 | * element, traveling clockwise. 12 | */ 13 | 14 | import org.junit.Assert; 15 | import org.junit.Test; 16 | 17 | import java.util.Arrays; 18 | import static java.util.stream.Collectors.joining; 19 | 20 | public class SnailSort { 21 | public static int[] snail(int[][] array) { 22 | if (array == null || array.length == 0 || array.length == 1 && array[0].length == 0) { 23 | return new int[0]; 24 | } 25 | 26 | final int height = array.length; 27 | final int width = array[0].length; 28 | final int lastY = height / 2; 29 | final int lastX = width % 2 == 0 ? width / 2 - 1 : width / 2; 30 | 31 | int y = 0, x = 0, dirX = 1, dirY = 0, i = 0; 32 | int leftBorder = -1, rightBorder = width; 33 | int upperBorder = -1, lowerBorder = height; 34 | int[] output = new int[height * width]; 35 | 36 | while (true) { 37 | if (x == rightBorder && y == upperBorder + 1) { 38 | x--; 39 | y++; 40 | dirX = 0; 41 | dirY = 1; 42 | upperBorder++; 43 | } else if (x == leftBorder && y == lowerBorder - 1) { 44 | x++; 45 | y--; 46 | dirX = 0; 47 | dirY = -1; 48 | lowerBorder--; 49 | } else if (y == lowerBorder && x == rightBorder - 1) { 50 | y--; 51 | x--; 52 | dirX = -1; 53 | dirY = 0; 54 | rightBorder--; 55 | } else if (y == upperBorder && x == leftBorder + 1) { 56 | y++; 57 | x++; 58 | dirX = 1; 59 | dirY = 0; 60 | leftBorder++; 61 | } 62 | output[i] = array[y][x]; 63 | 64 | if (y == lastY && x == lastX) { 65 | break; 66 | } 67 | 68 | x += dirX; 69 | y += dirY; 70 | i++; 71 | } 72 | 73 | return output; 74 | } 75 | 76 | @Test 77 | public void SnailTest1() { 78 | int[][] array 79 | = {{1, 2, 3}, 80 | {4, 5, 6}, 81 | {7, 8, 9}}; 82 | int[] r = {1, 2, 3, 6, 9, 8, 7, 4, 5}; 83 | test(array, r); 84 | } 85 | 86 | public String int2dToString(int[][] a) { 87 | return Arrays.stream(a).map(row -> Arrays.toString(row)).collect(joining("\n")); 88 | } 89 | 90 | public void test(int[][] array, int[] result) { 91 | String text = int2dToString(array) + " should be sorted to " + Arrays.toString(result); 92 | System.out.println(text); 93 | Assert.assertArrayEquals( result, snail(array)); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/kyu4/StringsMix.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Strings mix 5 | * 6 | * https://www.codewars.com/kata/5629db57620258aa9d000014 7 | * 8 | * Details: 9 | * 10 | * Given two strings s1 and s2, we want to visualize how different the two strings are. We will 11 | * only take into account the lowercase letters (a to z). First let us count the frequency of each 12 | * lowercase letters in s1 and s2. 13 | * 14 | * s1 = "A aaaa bb c" 15 | * 16 | * s2 = "& aaa bbb c d" 17 | * 18 | * s1 has 4 'a', 2 'b', 1 'c' 19 | * 20 | * s2 has 3 'a', 3 'b', 1 'c', 1 'd' 21 | * 22 | * So the maximum for 'a' in s1 and s2 is 4 from s1; the maximum for 'b' is 3 from s2. In the 23 | * following we will not consider letters when the maximum of their occurrences is less than or 24 | * equal to 1. 25 | * 26 | * We can resume the differences between s1 and s2 in the following string: "1:aaaa/2:bbb" where 27 | * 1 in 1:aaaa stands for string s1 and aaaa because the maximum for a is 4. In the same manner 28 | * 2:bbb stands for string s2 and bbb because the maximum for b is 3. 29 | * 30 | * The task is to produce a string in which each lowercase letters of s1 or s2 appears as many 31 | * times as its maximum if this maximum is strictly greater than 1; these letters will be prefixed 32 | * by the number of the string where they appear with their maximum value and :. If the maximum is 33 | * in s1 as well as in s2 the prefix is =:. 34 | * 35 | * In the result, substrings (a substring is for example 2:nnnnn or 1:hhh; it contains the prefix) 36 | * will be in decreasing order of their length and when they have the same length sorted in 37 | * ascending lexicographic order (letters and digits - more precisely sorted by codepoint); 38 | * the different groups will be separated by '/'. See examples and "Example Tests". 39 | */ 40 | 41 | import org.junit.Test; 42 | 43 | import java.nio.CharBuffer; 44 | import java.util.ArrayList; 45 | import java.util.Comparator; 46 | import java.util.List; 47 | import java.util.Map; 48 | import java.util.function.Function; 49 | import java.util.stream.Collectors; 50 | 51 | import static org.junit.Assert.assertEquals; 52 | 53 | public class StringsMix { 54 | public static String mix(String s1, String s2) { 55 | if (s1.equals(s2)) { 56 | return ""; 57 | } 58 | 59 | final Map charactersFromS1 = calculateCharacterFrequency(s1); 60 | final Map charactersFromS2 = calculateCharacterFrequency(s2); 61 | final List allCharacters = new ArrayList<>(charactersFromS1.keySet()); 62 | 63 | for (char c : new ArrayList<>(charactersFromS2.keySet())) { 64 | if (!allCharacters.contains(c)) { 65 | allCharacters.add(c); 66 | } 67 | } 68 | 69 | List result = new ArrayList<>(); 70 | 71 | for (int i = 0; i < allCharacters.size(); i++) { 72 | final StringBuilder sb = new StringBuilder(); 73 | final char current = allCharacters.get(i); 74 | final long frequency_1 = charactersFromS1.getOrDefault(current, 0L); 75 | final long frequency_2 = charactersFromS2.getOrDefault(current, 0L); 76 | final long frequency = Math.max(frequency_1, frequency_2); 77 | 78 | if (frequency_1 == frequency_2) { 79 | sb.append('='); 80 | } else { 81 | sb.append(frequency_1 > frequency_2 ? '1' : '2'); 82 | } 83 | sb.append(':'); 84 | 85 | for (int j = 0; j < frequency; j++) { 86 | sb.append(current); 87 | } 88 | 89 | result.add(sb.toString()); 90 | } 91 | 92 | return result.stream() 93 | .sorted(Comparator.comparing(String::length) 94 | .reversed() 95 | .thenComparing(s -> s.length() == 0 ? -1 : s.charAt(0)) 96 | .thenComparing(Function.identity())) 97 | .collect(Collectors.joining("/")); 98 | } 99 | 100 | private static Map calculateCharacterFrequency(String s) { 101 | return CharBuffer.wrap(s.toCharArray()) 102 | .chars() 103 | .mapToObj(ch -> (char) ch) 104 | .filter(c -> Character.isAlphabetic(c)) 105 | .filter(c -> Character.toUpperCase(c) != c) 106 | .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) 107 | .entrySet() 108 | .stream() 109 | .filter(e -> e.getValue() > 1) 110 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 111 | } 112 | 113 | @Test 114 | public void test() { 115 | System.out.println("Mix Fixed Tests"); 116 | assertEquals("1:aaa/1:nnn/1:gg/2:ee/2:ff/2:ii/2:oo/2:rr/2:ss/2:tt", 117 | mix(" In many languages", " there's a pair of functions")); 118 | } 119 | } -------------------------------------------------------------------------------- /src/main/java/kyu4/StripComments.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Strip Comments 5 | * 6 | * https://www.codewars.com/kata/51c8e37cee245da6b40000bd/ 7 | * 8 | * Details: 9 | * 10 | * Complete the solution so that it strips all text that follows any of a set of comment markers 11 | * passed in. Any whitespace at the end of the line should also be stripped out. 12 | */ 13 | 14 | import static org.junit.Assert.assertEquals; 15 | 16 | import org.junit.Test; 17 | 18 | public class StripComments { 19 | public static String stripComments(String text, String[] commentSymbols) { 20 | if (text.length() == 0 || text.isEmpty()) { 21 | return null; 22 | } 23 | 24 | final StringBuilder sb = new StringBuilder(); 25 | final String[] lines = text.split("\n"); 26 | 27 | for (int i = 0; i < lines.length; i++) { 28 | final String s = lines[i]; 29 | final StringBuilder helper = new StringBuilder(); 30 | int commentStartPosition = s.length(); 31 | 32 | if (commentStartPosition !=0) { 33 | for (String comment : commentSymbols) { 34 | if (s.contains(comment)) { 35 | commentStartPosition = Math.min(commentStartPosition, s.indexOf(comment)); 36 | } 37 | } 38 | helper.append(s, 0, commentStartPosition); 39 | } 40 | 41 | while (helper.length() !=0 && helper.charAt(helper.length() - 1) == ' ') { 42 | helper.setLength(helper.length() - 1); 43 | } 44 | 45 | helper.append("\n"); 46 | sb.append(helper); 47 | } 48 | 49 | if (sb.length() != 0) { 50 | sb.setLength(sb.length() - 1); 51 | } 52 | 53 | return new String(sb); 54 | } 55 | 56 | @Test 57 | public void stripComments() throws Exception { 58 | assertEquals( 59 | "apples, pears\ngrapes\nbananas", 60 | StripComments.stripComments("apples, pears # and bananas\ngrapes\nbananas !apples", new String[]{"#", "!"}) 61 | ); 62 | 63 | assertEquals( 64 | "a\nc\nd", 65 | StripComments.stripComments("a #b\nc\nd $e f g", new String[]{"#", "$"}) 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/kyu4/SudokuSolutionValidator.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Sudoku Solution Validator 5 | * 6 | * https://www.codewars.com/kata/529bf0e9bdf7657179000008/ 7 | * 8 | * Details: 9 | * 10 | * Sudoku is a game played on a 9x9 grid. The goal of the game is to fill all cells of the grid 11 | * with digits from 1 to 9, so that each column, each row, and each of the nine 3x3 sub-grids 12 | * (also known as blocks) contain all of the digits from 1 to 9. 13 | * (More info at: http://en.wikipedia.org/wiki/Sudoku) 14 | * 15 | * Sudoku Solution Validator 16 | * 17 | * Write a function validSolution/ValidateSolution/valid_solution() that accepts a 2D array 18 | * representing a Sudoku board, and returns true if it is a valid solution, or false otherwise. 19 | * The cells of the sudoku board may also contain 0's, which will represent empty cells. Boards 20 | * containing one or more zeroes are considered to be invalid solutions. 21 | * 22 | * The board is always 9 cells by 9 cells, and every cell only contains integers from 0 to 9. 23 | */ 24 | 25 | import java.util.ArrayList; 26 | import java.util.Collections; 27 | 28 | import org.junit.Test; 29 | 30 | import static org.junit.Assert.assertEquals; 31 | 32 | public class SudokuSolutionValidator { 33 | private static int size; 34 | private static ArrayList values; 35 | 36 | public static boolean check(int[][] sudoku) { 37 | size = sudoku.length; 38 | values = new ArrayList<>(size); 39 | return check(sudoku, true) && check(sudoku, false) && blocksCheck(sudoku); 40 | } 41 | 42 | private final static boolean blocksCheck(int[][] sudoku) { 43 | for (int y = 0; y < size; y += 3) { 44 | for (int x = 0; x < size; x += 3) { 45 | for (int j = y; j < y + 3; j++) { 46 | for (int i = x; i < x + 3; i++) { 47 | values.add(sudoku[j][i]); 48 | } 49 | } 50 | System.out.println(values.size()); 51 | 52 | if (!validateSection()) { 53 | return false; 54 | } 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | private final static boolean validateSection() { 61 | if (values.size() != size) { 62 | return false; 63 | } 64 | 65 | Collections.sort(values); 66 | 67 | if (values.get(0) != 1) { 68 | return false; 69 | } 70 | 71 | for (int i = 1; i < size; i++) { 72 | if (values.get(i) - values.get(i-1) != 1) { 73 | return false; 74 | } 75 | } 76 | 77 | values.clear(); 78 | 79 | return true; 80 | } 81 | 82 | private final static boolean check(int[][] sudoku, boolean isFlipped) { 83 | for (int y = 0; y < size; y++) { 84 | for (int x = 0; x < size; x++) { 85 | int i; 86 | int j; 87 | 88 | if (isFlipped) { 89 | i = x; 90 | j = y; 91 | } else { 92 | i = y; 93 | j = x; 94 | } 95 | 96 | if (sudoku[i][j] == 0) { 97 | return false; 98 | } 99 | values.add(sudoku[i][j]); 100 | } 101 | 102 | if (!validateSection()) { 103 | return false; 104 | } 105 | } 106 | 107 | return true; 108 | } 109 | 110 | @Test 111 | public void exampleTest() { 112 | int[][] sudoku = { 113 | {9, 8, 7, 2, 3, 1, 5, 4, 6}, 114 | {6, 5, 4, 8, 9, 7, 2, 1, 3}, 115 | {3, 2, 1, 5, 6, 4, 8, 7, 9}, 116 | {7, 6, 5, 9, 1, 8, 3, 2, 4}, 117 | {4, 3, 2, 6, 7, 5, 9, 8, 1}, 118 | {1, 9, 8, 3, 4, 2, 6, 5, 7}, 119 | {8, 7, 6, 1, 2, 9, 4, 3, 5}, 120 | {5, 4, 3, 7, 8, 6, 1, 9, 2}, 121 | {2, 1, 9, 4, 5, 3, 7, 6, 8} 122 | }; 123 | assertEquals(true, check(sudoku)); 124 | 125 | sudoku[0][0]++; 126 | sudoku[1][1]++; 127 | sudoku[0][1]--; 128 | sudoku[1][0]--; 129 | 130 | assertEquals(false, check(sudoku)); 131 | 132 | sudoku[0][0]--; 133 | sudoku[1][1]--; 134 | sudoku[0][1]++; 135 | sudoku[1][0]++; 136 | 137 | sudoku[4][4] = 0; 138 | 139 | assertEquals(false, check(sudoku)); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/kyu4/TimeFormatter.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Human readable duration format 5 | * 6 | * https://www.codewars.com/kata/52742f58faf5485cae000b9a/train/java 7 | * 8 | * Details: 9 | * 10 | * our task in order to complete this Kata is to write a function which formats a duration, given 11 | * as a number of seconds, in a human-friendly way. 12 | * 13 | * The function must accept a non-negative integer. If it is zero, it just returns "now". 14 | * Otherwise, the duration is expressed as a combination of years, days, hours, minutes and 15 | * seconds. 16 | * 17 | * For the purpose of this Kata, a year is 365 days and a day is 24 hours. 18 | * 19 | * Note that spaces are important. 20 | * Detailed rules 21 | * 22 | * The resulting expression is made of components like 4 seconds, 1 year, etc. In general, a 23 | * positive integer and one of the valid units of time, separated by a space. The unit of time is 24 | * used in plural if the integer is greater than 1. 25 | * 26 | * The components are separated by a comma and a space (", "). Except the last component, which is 27 | * separated by " and ", just like it would be written in English. 28 | * 29 | * A more significant units of time will occur before than a least significant one. Therefore, 1 30 | * second and 1 year is not correct, but 1 year and 1 second is. 31 | * 32 | * Different components have different unit of times. So there is not repeated units like in 5 33 | * seconds and 1 second. 34 | * 35 | * A component will not appear at all if its value happens to be zero. Hence, 1 minute and 0 36 | * seconds is not valid, but it should be just 1 minute. 37 | * 38 | * A unit of time must be used "as much as possible". It means that the function should not return 39 | * 61 seconds, but 1 minute and 1 second instead. Formally, the duration specified by of a 40 | * component must not be greater than any valid more significant unit of time. 41 | */ 42 | 43 | import org.junit.jupiter.api.Test; 44 | 45 | import java.util.*; 46 | 47 | import static org.junit.jupiter.api.Assertions.assertEquals; 48 | 49 | public class TimeFormatter { 50 | static class TimeUnit { 51 | private String name; 52 | private int value; 53 | 54 | TimeUnit(String name, int value) { 55 | this.name = name; 56 | this.value = value; 57 | } 58 | } 59 | 60 | public static String formatDuration(int seconds) { 61 | if (seconds <= 0) { 62 | return "now"; 63 | } 64 | 65 | List time = new ArrayList<>(); 66 | time.add(new TimeUnit("year", (seconds / (60 * 60 * 24 * 365)))); 67 | time.add(new TimeUnit("day", (seconds / (60 * 60 * 24)) % 365)); 68 | time.add(new TimeUnit("hour", (seconds / (60 * 60)) % 24)); 69 | time.add(new TimeUnit("minute", (seconds / 60) % 60)); 70 | time.add(new TimeUnit("second", seconds % 60)); 71 | 72 | time.removeIf(timeUnit -> timeUnit.value == 0); 73 | 74 | StringBuilder sb = new StringBuilder(); 75 | 76 | for (int i = 0; i < time.size(); i++) { 77 | final TimeUnit unit = time.get(i); 78 | 79 | sb.append(unit.value) 80 | .append(" ") 81 | .append(unit.name); 82 | 83 | if (unit.value > 1) { 84 | sb.append("s"); 85 | } else if (i < time.size() - 2) { 86 | sb.append(", "); 87 | } else if (i == time.size() - 2) { 88 | sb.append(" and "); 89 | } 90 | } 91 | 92 | return new String(sb); 93 | } 94 | 95 | @Test 96 | public void exampleTests() { 97 | assertEquals("1 second", TimeFormatter.formatDuration(1)); 98 | assertEquals("1 minute and 2 seconds", TimeFormatter.formatDuration(62)); 99 | assertEquals("2 minutes", TimeFormatter.formatDuration(120)); 100 | assertEquals("1 hour", TimeFormatter.formatDuration(3600)); 101 | assertEquals("1 hour, 1 minute and 2 seconds", TimeFormatter.formatDuration(3662)); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/kyu4/TopWords.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu4; 2 | 3 | /** 4 | * 4 kyu - Most frequently used words in a text 5 | *

6 | * https://www.codewars.com/kata/51e056fe544cf36c410000fb/ 7 | *

8 | * Details: 9 | *

10 | * Write a function that, given a string of text (possibly with punctuation and line-breaks), 11 | * returns an array of the top-3 most occurring words, in descending order of the number of occurrences. 12 | * Assumptions: 13 | *

14 | * A word is a string of letters (A to Z) optionally containing one or more apostrophes (') in 15 | * ASCII. (No need to handle fancy punctuation.) 16 | * Matches should be case-insensitive, and the words in the result should be lowercased. 17 | * Ties may be broken arbitrarily. 18 | * If a text contains fewer than three unique words, then either the top-2 or top-1 words 19 | * should be returned, or an empty array if a text contains no words. 20 | */ 21 | 22 | import java.util.*; 23 | import java.util.regex.Matcher; 24 | import java.util.regex.Pattern; 25 | import java.util.stream.Collectors; 26 | 27 | public class TopWords { 28 | public static final int LIMIT = 3; 29 | 30 | public static List top3(String string) { 31 | final Map wordsCount = new HashMap<>(); 32 | 33 | Pattern pattern = Pattern.compile("[A-Za-z][A-Za-z']*"); 34 | Matcher matcher = pattern.matcher(string); 35 | while (matcher.find()) { 36 | String s = matcher.group().toLowerCase(); 37 | wordsCount.put(s, wordsCount.getOrDefault(s, 1) + 1); 38 | } 39 | 40 | List> topWords = new ArrayList<>(wordsCount.entrySet()); 41 | topWords.sort(Map.Entry.comparingByValue()); 42 | ArrayList result = new ArrayList<>(); 43 | int j = 0; 44 | for (int i = topWords.size() - 1; i >= 0; i--) { 45 | String s = topWords.get(i).getKey(); 46 | if (j > 2 || s == null || s.length() == 0) { 47 | break; 48 | } 49 | if (Character.isAlphabetic(s.charAt(0))) { 50 | result.add(j, topWords.get(i).getKey()); 51 | j++; 52 | } 53 | } 54 | 55 | result.trimToSize(); 56 | return result; 57 | } 58 | 59 | public static List top3_streams(String string) { 60 | final Pattern pattern = Pattern.compile("[A-Za-z][A-Za-z']*"); 61 | final Matcher matcher = pattern.matcher(string.toLowerCase()); 62 | final Map wordsCount = new HashMap<>(); 63 | 64 | while (matcher.find()) { 65 | String s = matcher.group(); 66 | wordsCount.put(s, wordsCount.getOrDefault(s, 1) + 1); 67 | } 68 | 69 | return wordsCount.entrySet().stream() 70 | .sorted(Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder())) 71 | .limit(LIMIT) 72 | .map(Map.Entry::getKey) 73 | .collect(Collectors.toList()); 74 | } 75 | } -------------------------------------------------------------------------------- /src/main/java/kyu5/DoubleCola.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - Double Cola 5 | * 6 | * https://www.codewars.com/kata/551dd1f424b7a4cdae0001f0 7 | * 8 | * Details: 9 | * 10 | * Sheldon, Leonard, Penny, Rajesh and Howard are in the queue for a "Double Cola" drink vending 11 | * machine; there are no other people in the queue. The first one in the queue (Sheldon) buys a 12 | * can, drinks it and doubles! The resulting two Sheldons go to the end of the queue. Then the 13 | * next in the queue (Leonard) buys a can, drinks it and gets to the end of the queue as two 14 | * Leonards, and so on. 15 | * 16 | * For example, Penny drinks the third can of cola and the queue will look like this: 17 | * 18 | * Rajesh, Howard, Sheldon, Sheldon, Leonard, Leonard, Penny, Penny 19 | * 20 | * Write a program that will return the name of the person who will drink the n-th cola. 21 | * Input 22 | * 23 | * The input data consist of an array which contains at least 1 name, and single integer n which 24 | * may go as high as the biggest number your language of choice supports (if there's such limit, 25 | * of course). 26 | * Output / Examples 27 | * 28 | * Return the single line — the name of the person who drinks the n-th can of cola. The cans are 29 | * numbered starting from 1. 30 | */ 31 | 32 | import org.junit.Test; 33 | 34 | import static org.junit.Assert.assertEquals; 35 | 36 | public class DoubleCola { 37 | public static String WhoIsNext(String[] names, int n) { 38 | int i = n; 39 | i--; 40 | 41 | final int len = names.length; 42 | while (i >= len) { 43 | i = (int) Math.floor((i - names.length) / 2); 44 | } 45 | 46 | return names[i]; 47 | } 48 | 49 | @Test 50 | public void test1() { 51 | String[] names = new String[]{"Sheldon", "Leonard", "Penny", "Rajesh", "Howard"}; 52 | int n = 1; 53 | assertEquals("Sheldon", WhoIsNext(names, n)); 54 | } 55 | 56 | @Test 57 | public void test2() { 58 | String[] names = new String[]{"Sheldon", "Leonard", "Penny", "Rajesh", "Howard"}; 59 | int n = 6; 60 | assertEquals("Sheldon", WhoIsNext(names, n)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/kyu5/FactorialDecomposition.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - Factorial Decomposition 5 | * 6 | * https://www.codewars.com/kata/5a045fee46d843effa000070 7 | * 8 | * Details: 9 | * 10 | * The aim of the kata is to decompose n! (factorial n) into its prime factors. 11 | * 12 | * Prime numbers should be in increasing order. When the exponent of a prime is 1 don't put the 13 | * exponent. 14 | * 15 | * Notes 16 | * 17 | * - the function is decomp(n) and should return the decomposition of n! into its prime factors 18 | * in increasing order of the primes, as a string. 19 | * - factorial can be a very big number (4000! has 12674 digits, n will go from 300 to 4000). 20 | * - In Fortran - as in any other language - the returned string is not permitted to contain 21 | * any redundant trailing whitespace: you can use dynamically allocated character strings. 22 | */ 23 | 24 | import org.junit.jupiter.api.Test; 25 | 26 | import java.util.*; 27 | 28 | import static org.junit.jupiter.api.Assertions.assertEquals; 29 | 30 | public class FactorialDecomposition { 31 | public static String decomp(int n) { 32 | if (n == 1) { 33 | return "1"; 34 | } 35 | 36 | LinkedHashMap decomposition = new LinkedHashMap<>(); 37 | 38 | for (int i = 2; i <= n; i++) { 39 | int currentNum = i; 40 | int counter = 0; 41 | 42 | for (int k = 2; k <= i; ) { 43 | final int remainder = currentNum % k; 44 | 45 | if (remainder != 0 || currentNum <= 1) { 46 | if (counter !=0) { 47 | if (decomposition.containsKey(k)) { 48 | decomposition.put(k,decomposition.get(k) + counter); 49 | } else { 50 | decomposition.put(k, counter); 51 | } 52 | } 53 | 54 | k++; 55 | counter = 0; 56 | } else { 57 | counter++; 58 | currentNum /= k; 59 | } 60 | } 61 | } 62 | 63 | final StringBuilder sb = new StringBuilder(); 64 | 65 | for (final Map.Entry entry : decomposition.entrySet()) { 66 | if (sb.length() != 0) { 67 | sb.append(" * "); 68 | } 69 | 70 | sb.append(entry.getKey()); 71 | 72 | if (entry.getValue() != 1) { 73 | sb.append("^").append(entry.getValue()); 74 | } 75 | } 76 | 77 | return new String(sb); 78 | } 79 | 80 | @Test 81 | public void test() { 82 | assertEquals("2^15 * 3^6 * 5^3 * 7^2 * 11 * 13 * 17", decomp(17)); 83 | assertEquals("2^3 * 3 * 5", decomp(5)); 84 | assertEquals("2^19 * 3^9 * 5^4 * 7^3 * 11^2 * 13 * 17 * 19", decomp(22)); 85 | assertEquals("2^11 * 3^5 * 5^2 * 7^2 * 11 * 13", decomp(14)); 86 | assertEquals("2^22 * 3^10 * 5^6 * 7^3 * 11^2 * 13 * 17 * 19 * 23", decomp(25)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/kyu5/HumanReadableTime.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - Human Readable time 5 | * 6 | * https://www.codewars.com/kata/52685f7382004e774f0001f7 7 | * 8 | * Details: 9 | * 10 | * Write a function, which takes a non-negative integer (seconds) as input and returns the time 11 | * in a human-readable format (HH:MM:SS) 12 | * 13 | * HH = hours, padded to 2 digits, range: 00 - 99 14 | * MM = minutes, padded to 2 digits, range: 00 - 59 15 | * SS = seconds, padded to 2 digits, range: 00 - 59 16 | * 17 | * The maximum time never exceeds 359999 (99:59:59) 18 | * 19 | * You can find some examples in the test fixtures. 20 | */ 21 | 22 | import org.junit.Test; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | 26 | public class HumanReadableTime { 27 | public static String makeReadable(int seconds) { 28 | int minutes = seconds / 60; 29 | int hours = minutes / 60; 30 | minutes -= hours * 60; 31 | return String.format("%02d:%02d:%02d", hours, minutes, seconds % 60); 32 | } 33 | 34 | @Test 35 | public void tests() { 36 | assertEquals("makeReadable(0)", "00:00:00", HumanReadableTime.makeReadable(0)); 37 | assertEquals("makeReadable(5)", "00:00:05", HumanReadableTime.makeReadable(5)); 38 | assertEquals("makeReadable(60)", "00:01:00", HumanReadableTime.makeReadable(60)); 39 | assertEquals("makeReadable(86399)", "23:59:59", HumanReadableTime.makeReadable(86399)); 40 | assertEquals("makeReadable(359999)", "99:59:59", HumanReadableTime.makeReadable(359999)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/kyu5/MergeIn2048.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - Merge in 2048 5 | * 6 | * https://www.codewars.com/kata/55e1990978c60e5052000011 7 | * 8 | * Details: 9 | * 10 | * Remember the game 2048? 11 | * 12 | * The main part of this game is merging identical tiles in a row. 13 | * 14 | * Implement a function that models the process of merging all of the tile values in a single 15 | * row. 16 | * This function takes the array line as a parameter and returns a new array with the tile 17 | * values from line slid towards the front of the array (index 0) and merged. 18 | * 19 | * A given tile can only merge once. 20 | * Empty grid squares are represented as zeros. 21 | * Your function should work on arrays containing arbitrary number of elements. 22 | */ 23 | 24 | import org.junit.Test; 25 | import static org.junit.Assert.assertArrayEquals; 26 | 27 | public class MergeIn2048 { 28 | public static int[] merge(int[] line) { 29 | if (line == null || line.length == 0) { 30 | return new int[0]; 31 | } 32 | 33 | compress(line); 34 | final boolean isMerged = add(line); 35 | 36 | if (isMerged) { 37 | compress(line); 38 | } 39 | 40 | return line; 41 | } 42 | 43 | private final static void compress(int[] row) { 44 | for (int i = 0; i < row.length; i++) { 45 | if (row[i] == 0) { 46 | for (int j = i; j < row.length; j++) { 47 | if (row[j] != 0) { 48 | row[i] = row[j]; 49 | row[j] = 0; 50 | break; 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | private final static boolean add(int[] row) { 58 | boolean isMerged = false; 59 | 60 | for (int i = 0; i < row.length-1 ; i++) { 61 | if (row[i] == row[i + 1] && row[i] != 0) { 62 | row[i] = row[i] * 2; 63 | row[i+1] = 0; 64 | i++; 65 | isMerged = true; 66 | } 67 | } 68 | 69 | return isMerged; 70 | } 71 | 72 | @Test 73 | public void sampleTests() { 74 | assertArrayEquals(new int[] {4,2,0,0}, merge(new int[] {2,0,2,2})); 75 | assertArrayEquals(new int[] {4,4,0,0}, merge(new int[] {2,0,2,4})); 76 | assertArrayEquals(new int[] {4,0,0,0}, merge(new int[] {0,0,2,2})); 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/main/java/kyu5/Scramblies.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - Scramblies 5 | *

6 | * https://www.codewars.com/kata/55c04b4cc56a697bb0000048 7 | *

8 | * Details: 9 | *

10 | * Complete the function scramble(str1, str2) that returns true if a portion of str1 characters 11 | * can be rearranged to match str2, otherwise returns false. 12 | *

13 | * Notes: 14 | *

15 | * Only lower case letters will be used (a-z). No punctuation or digits will be included. 16 | * Performance needs to be considered 17 | */ 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | public class Scramblies { 23 | 24 | public static boolean scramble(String str1, String str2) { 25 | if (str2 == null || str2.length() == 0) { 26 | return true; 27 | } 28 | HashMap s1 = new HashMap<>(); 29 | HashMap s2 = new HashMap<>(); 30 | 31 | for (char ch : str1.toCharArray()) { 32 | char current = Character.toLowerCase(ch); 33 | s1.put(current, s1.getOrDefault(current, 0) + 1); 34 | } 35 | 36 | for (char ch : str2.toCharArray()) { 37 | char current = Character.toLowerCase(ch); 38 | s2.put(current, s2.getOrDefault(current, 0) + 1); 39 | } 40 | 41 | for (Map.Entry entry : s2.entrySet()) { 42 | try { 43 | if (entry.getValue() > s1.get(entry.getKey())) { 44 | return false; 45 | } 46 | } catch (NullPointerException e) { 47 | return false; 48 | } 49 | } 50 | 51 | return true; 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/java/kyu5/SimplePigLatin.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - Simple Pig Latin 5 | *

6 | * https://www.codewars.com/kata/520b9d2ad5c005041100000f 7 | *

8 | * Details: 9 | *

10 | * Move the first letter of each word to the end of it, 11 | * then add "ay" to the end of the word. Leave punctuation marks untouched. 12 | */ 13 | 14 | import org.junit.Test; 15 | 16 | import java.util.regex.Pattern; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | 20 | public class SimplePigLatin { 21 | public static String pigIt(String str) { 22 | if (str == null || str.length() == 0) { 23 | return null; 24 | } 25 | 26 | final String[] words = str.split("\\s"); 27 | final StringBuilder sb = new StringBuilder(); 28 | 29 | for (String s : words) { 30 | if (Pattern.matches("\\p{IsPunctuation}", s)) { 31 | sb.append(s) 32 | .append(" "); 33 | } else { 34 | sb.append(s.substring(1)) 35 | .append(s.charAt(0)) 36 | .append("ay "); 37 | } 38 | } 39 | 40 | while (sb.charAt(sb.length() - 1) == ' ') { 41 | sb.setLength(sb.length() - 1); 42 | } 43 | 44 | return new String(sb); 45 | } 46 | 47 | @Test 48 | public void fixedTests() { 49 | assertEquals("igPay atinlay siay oolcay", pigIt("Pig latin is cool")); 50 | assertEquals("hisTay siay ymay tringsay", pigIt("This is my string")); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/kyu5/SnakesLadders.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - Snakes and Ladders 5 | * 6 | * https://www.codewars.com/kata/587136ba2eefcb92a9000027 7 | * 8 | * Details: 9 | * 10 | * Snakes and Ladders is an ancient Indian board game regarded today as a worldwide classic. It is 11 | * played between two or more players on a gameboard having numbered, gridded squares. A number 12 | * of "ladders" and "snakes" are pictured on the board, each connecting two specific board 13 | * squares. (Source Wikipedia) 14 | * 15 | * Your task is to make a simple class called SnakesLadders. The test cases will call the method 16 | * play(die1, die2) independently of the state of the game or the player turn. The variables die1 17 | * and die2 are the die thrown in a turn and are both integers between 1 and 6. The player will 18 | * move the sum of die1 and die2. 19 | * 20 | * Rules: 21 | * 1. There are two players and both start off the board on square 0. 22 | * 2. Player 1 starts and alternates with player 2. 23 | * 3. You follow the numbers up the board in order 1=>100 24 | * 4. If the value of both die are the same then that player will have another go. 25 | * 5. Climb up ladders. The ladders on the game board allow you to move upwards and get ahead 26 | * faster. If you land exactly on a square that shows an image of the bottom of a ladder, then 27 | * you may move the player all the way up to the square at the top of the ladder. (even if you 28 | * roll a double). 29 | * 6. Slide down snakes. Snakes move you back on the board because you have to slide down them. 30 | * If you land exactly at the top of a snake, slide move the player all the way to the square 31 | * at the bottom of the snake or chute. (even if you roll a double). 32 | * 7. Land exactly on the last square to win. The first person to reach the highest square on 33 | * the board wins. But there's a twist! If you roll too high, your player "bounces" off the 34 | * last square and moves back. You can only win by rolling the exact number needed to land on 35 | * the last square. For example, if you are on square 98 and roll a five, move your game piece 36 | * to 100 (two moves), then "bounce" back to 99, 98, 97 (three, four then five moves.) 37 | * 8. If the Player rolled a double and lands on the finish square “100” without any remaining 38 | * moves then the Player wins the game and does not have to roll again. 39 | */ 40 | 41 | import java.util.ArrayList; 42 | 43 | public class SnakesLadders { 44 | private ArrayList players = new ArrayList<>(); 45 | private ArrayList modifiers = new ArrayList<>(); 46 | private boolean isGameStopped; 47 | 48 | public SnakesLadders() { 49 | players.add(new Player(1, true)); 50 | players.add(new Player(2)); 51 | 52 | modifiers.add(new Ladder(2,38)); 53 | modifiers.add(new Ladder(7,14)); 54 | modifiers.add(new Ladder(8,31)); 55 | modifiers.add(new Ladder(7,14)); 56 | modifiers.add(new Ladder(8,31)); 57 | modifiers.add(new Ladder(15,26)); 58 | modifiers.add(new Ladder(21,42)); 59 | modifiers.add(new Ladder(28,84)); 60 | modifiers.add(new Ladder(36,44)); 61 | modifiers.add(new Ladder(51,67)); 62 | modifiers.add(new Ladder(71,91)); 63 | modifiers.add(new Ladder(78,98)); 64 | modifiers.add(new Ladder(87,94)); 65 | 66 | modifiers.add(new Slope(16,6)); 67 | modifiers.add(new Slope(46,25)); 68 | modifiers.add(new Slope(49,11)); 69 | modifiers.add(new Slope(62,19)); 70 | modifiers.add(new Slope(64,60)); 71 | modifiers.add(new Slope(74,53)); 72 | modifiers.add(new Slope(89,68)); 73 | modifiers.add(new Slope(92,88)); 74 | modifiers.add(new Slope(95,75)); 75 | modifiers.add(new Slope(99,80)); 76 | 77 | isGameStopped = false; 78 | } 79 | 80 | class Ladder { 81 | private int startX, endX; 82 | 83 | public Ladder(int startX, int endX) { 84 | this.startX = startX; 85 | this.endX = endX; 86 | } 87 | } 88 | 89 | class Slope extends Ladder { 90 | public Slope(int startX, int endX) { 91 | super(startX, endX); 92 | } 93 | } 94 | 95 | class Player { 96 | private int id, x; 97 | private boolean isWinner, isCurrentTurn; 98 | 99 | public Player(int id) { 100 | this.id = id; 101 | } 102 | 103 | public Player(int id, boolean isCurrentTurn) { 104 | this.id = id; 105 | this.isCurrentTurn = isCurrentTurn; 106 | } 107 | } 108 | 109 | private String currentState(Player p) { 110 | if (p.x == 100 && !isGameStopped) { 111 | p.isWinner = true; 112 | isGameStopped = true; 113 | return String.format("Player %d Wins!", p.id); 114 | } else { 115 | if (isGameStopped) { 116 | return ("Game over!"); 117 | } 118 | return String.format("Player %d is on square %d", p.id, p.x); 119 | } 120 | } 121 | 122 | private void checkPosition(Player p) { 123 | modifiers.forEach(m -> { 124 | if (m.startX == p.x) { 125 | p.x = m.endX; 126 | } 127 | }); 128 | } 129 | 130 | public String play(int die1, int die2) { 131 | for (int i = 0; i < players.size(); i++) { 132 | if (players.get(i).isCurrentTurn) { 133 | players.get(i).x += die1 + die2; 134 | 135 | if (players.get(i).x > 100) { 136 | players.get(i).x = 100 - (players.get(i).x - 100); 137 | } 138 | 139 | checkPosition(players.get(i)); 140 | 141 | if (die1 != die2) { 142 | players.get(i).isCurrentTurn = false; 143 | 144 | if (i != players.size() - 1) { 145 | players.get(i + 1).isCurrentTurn = true; 146 | } else { 147 | players.get(0).isCurrentTurn = true; 148 | } 149 | } 150 | return currentState(players.get(i)); 151 | } 152 | } 153 | return null; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/kyu5/WhatsThePerfectPowerAnyway.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu5; 2 | 3 | /** 4 | * 5 kyu - What's the Perfect Power anyway? 5 | *

6 | * https://www.codewars.com/kata/54d4c8b08776e4ad92000835 7 | *

8 | * Details: 9 | *

10 | * A perfect power is a classification of positive integers: 11 | *

12 | * In mathematics, a perfect power is a positive integer that can be expressed as an integer 13 | * power of another positive integer. More formally, n is a perfect power if there exist 14 | * natural numbers m > 1, and k > 1 such that mk = n. 15 | *

16 | * Your task is to check wheter a given integer is a perfect power. If it is a perfect power, 17 | * return a pair m and k with mk = n as a proof. Otherwise return Nothing, Nil, null, NULL, None 18 | * or your language's equivalent. 19 | *

20 | * Note: For a perfect power, there might be several pairs. For example 81 = 3^4 = 9^2, so (3,4) 21 | * and (9,2) are valid solutions. However, the tests take care of this, so if a number is a perfect 22 | * power, return any pair that proves it. 23 | */ 24 | 25 | import org.junit.Assert; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import java.util.Random; 29 | 30 | import static java.lang.Math.log; 31 | 32 | 33 | public class WhatsThePerfectPowerAnyway { 34 | public static int[] isPerfectPower(int n) { 35 | final double sqrt = Math.sqrt(n); 36 | for (int i = 2, j = 2; i <= sqrt; ) { 37 | final int currentPow = (int) Math.pow(i, j); 38 | 39 | if (currentPow == n) { 40 | return new int[]{i, j}; 41 | } else if (currentPow > n) { 42 | i++; 43 | j = 2; 44 | } else { 45 | j++; 46 | } 47 | } 48 | return null; 49 | } 50 | 51 | private static int ipow(int b, int e) { 52 | int i = b; 53 | int p = 1; 54 | for (; e > 0; e >>= 1) { 55 | if ((e & 1) == 1) p *= i; 56 | i *= i; 57 | } 58 | return p; 59 | } 60 | 61 | @Test 62 | public void test0() { 63 | Assert.assertNull("0 is not a perfect number", isPerfectPower(0)); 64 | } 65 | 66 | @Test 67 | public void test1() { 68 | Assert.assertNull("1 is not a perfect number", isPerfectPower(1)); 69 | } 70 | 71 | @Test 72 | public void test2() { 73 | Assert.assertNull("2 is not a perfect number", isPerfectPower(2)); 74 | } 75 | 76 | @Test 77 | public void test3() { 78 | Assert.assertNull("3 is not a perfect number", isPerfectPower(3)); 79 | } 80 | 81 | @Test 82 | public void test4() { 83 | Assert.assertArrayEquals("4 = 2^2", new int[]{2, 2}, isPerfectPower(4)); 84 | } 85 | 86 | @Test 87 | public void test5() { 88 | Assert.assertNull("5 is not a perfect power", isPerfectPower(5)); 89 | } 90 | 91 | @Test 92 | public void test8() { 93 | Assert.assertArrayEquals("8 = 2^3", new int[]{2, 3}, isPerfectPower(8)); 94 | } 95 | 96 | @Test 97 | public void test9() { 98 | Assert.assertArrayEquals("9 = 3^2", new int[]{3, 2}, isPerfectPower(9)); 99 | } 100 | 101 | @Test 102 | public void testUpTo500() { 103 | int[] pp = {4, 8, 9, 16, 25, 27, 32, 36, 49, 64, 81, 100, 121, 125, 128, 144, 169, 196, 216, 225, 243, 256, 289, 324, 343, 361, 400, 441, 484}; 104 | for (int i : pp) Assert.assertNotNull(i + " is a perfect power", isPerfectPower(i)); 105 | } 106 | 107 | @Test 108 | public void testRandomPerfectPowers() { 109 | Random rnd = new Random(); 110 | for (int i = 0; i < 100; i++) { 111 | int m = rnd.nextInt(254) + 2; 112 | int k = (int) (rnd.nextDouble() * (log(Integer.MAX_VALUE) / log(m) - 2.0) + 2.0); 113 | int l = ipow(m, k); 114 | int[] r = isPerfectPower(l); 115 | Assert.assertNotNull(l + " is a perfect power", r); 116 | Assert.assertEquals(r[0] + "^" + r[1] + "!=" + l, l, ipow(r[0], r[1])); 117 | } 118 | } 119 | 120 | @Test 121 | public void testRandomNumbers() { 122 | Random rnd = new Random(); 123 | for (int i = 0; i < 100; i++) { 124 | int l = rnd.nextInt(Integer.MAX_VALUE); 125 | int[] r = isPerfectPower(l); 126 | if (r != null) Assert.assertEquals(r[0] + "^" + r[1] + "!=" + l, l, ipow(r[0], r[1])); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/kyu6/AreTheyTheSame.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Are they the "same"? 5 | * 6 | * https://www.codewars.com/kata/550498447451fbbd7600041c 7 | * 8 | * Details: 9 | * 10 | * Given two arrays a and b write a function comp(a, b) (compSame(a, b) in Clojure) that checks 11 | * whether the two arrays have the "same" elements, with the same multiplicities. "Same" means, 12 | * here, that the elements in b are the elements in a squared, regardless of the order. 13 | */ 14 | 15 | import java.util.Arrays; 16 | 17 | public class AreTheyTheSame { 18 | public static boolean comp(int[] a, int[] b) { 19 | if (a == null || b == null) { 20 | return false; 21 | } else if (a.length == 0 || b.length == 0) { 22 | return a.length == b.length; 23 | } else { 24 | for (int i = 0; i < a.length; i++) { 25 | a[i] = Math.abs(a[i]); 26 | } 27 | 28 | for (int i = 0; i < b.length; i++) { 29 | b[i] = (int)Math.sqrt(b[i]); 30 | } 31 | 32 | Arrays.sort(a); 33 | Arrays.sort(b); 34 | 35 | for (int i = 0; i < a.length; i++) { 36 | if (a[i] != b[i]) { 37 | return false; 38 | } 39 | } 40 | } 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/kyu6/BreakCamelCase.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Break camelCase 5 | * 6 | * https://www.codewars.com/kata/5208f99aee097e6552000148 7 | * 8 | * Details: 9 | * 10 | * Complete the solution so that the function will break up camel casing, using a space between 11 | * words. 12 | */ 13 | 14 | public class BreakCamelCase { 15 | public static String camelCase(String input) { 16 | return input.replaceAll("([A-Z])", " $1"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/kyu6/BuyingACar.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Bying a car 5 | * 6 | * https://www.codewars.com/kata/554a44516729e4d80b000012/train/java 7 | * 8 | * Details: 9 | * 10 | * Let us begin with an example: 11 | * 12 | * A man has a rather old car being worth $2000. He saw a secondhand car being worth $8000. He 13 | * wants to keep his old car until he can buy the secondhand one. 14 | * 15 | * He thinks he can save $1000 each month but the prices of his old car and of the new one decrease 16 | * of 1.5 percent per month. Furthermore this percent of loss increases of 0.5 percent at the end 17 | * of every two months. Our man finds it difficult to make all these calculations. 18 | * 19 | * Can you help him? 20 | * 21 | * How many months will it take him to save up enough money to buy the car he wants, and how much 22 | * money will he have left over? 23 | */ 24 | 25 | import org.junit.jupiter.api.Assertions; 26 | import org.junit.jupiter.api.Test; 27 | 28 | public class BuyingACar { 29 | public static int[] nbMonths(int startPriceOld, int startPriceNew, int savingPerMonth, double percentLossByMonth) { 30 | if (startPriceNew <= startPriceOld) { 31 | return new int[]{0, startPriceOld - startPriceNew}; 32 | } 33 | 34 | double lossByMonth = percentLossByMonth; 35 | int passedMonths = 0; 36 | double currentDelta = startPriceOld - startPriceNew; 37 | double savingsLeft; 38 | 39 | do { 40 | passedMonths++; 41 | 42 | if (passedMonths % 2 == 0) { 43 | lossByMonth += 0.5; 44 | } 45 | 46 | currentDelta *= (1 - lossByMonth / 100); 47 | savingsLeft = passedMonths * savingPerMonth + currentDelta; 48 | 49 | System.out.println(String.format("End month: %d: percentLoss %.2f available %.3f", 50 | passedMonths, lossByMonth, savingsLeft)); 51 | } while (savingsLeft < 0); 52 | 53 | return new int[]{passedMonths, (int) Math.round(savingsLeft)}; 54 | } 55 | 56 | 57 | @Test 58 | void test1() { 59 | int[] r = new int[] { 6, 766 }; 60 | Assertions.assertArrayEquals(r, nbMonths(2000, 8000, 1000, 1.5)); 61 | } 62 | @Test 63 | void test2() { 64 | int[] r = new int[] { 0, 4000 }; 65 | Assertions.assertArrayEquals(r, nbMonths(12000, 8000, 1000, 1.5)); 66 | } 67 | @Test 68 | void test3() { 69 | int[] r = new int[] { 0, 0 }; 70 | Assertions.assertArrayEquals(r, nbMonths(8000, 8000, 1000, 1.5)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/kyu6/CamelCaseMethod.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - CamelCase Method 5 | * 6 | * https://www.codewars.com/kata/587731fda577b3d1b0001196 7 | * 8 | * Details: 9 | * 10 | * Write simple .camelCase method (camel_case function in PHP, CamelCase in C# or camelCase in 11 | * Java) for strings. All words must have their first letter capitalized without spaces. 12 | */ 13 | 14 | import org.junit.Test; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | 18 | public class CamelCaseMethod { 19 | public static String camelCase(String str) { 20 | final StringBuilder sb = new StringBuilder(); 21 | boolean isPreviousCharSpace = false; 22 | 23 | for (int i = 0; i < str.length(); i++) { 24 | final char current = str.charAt(i); 25 | 26 | if ((i == 0 || isPreviousCharSpace) && !Character.isWhitespace(current)) { 27 | sb.append(Character.toUpperCase(current)); 28 | isPreviousCharSpace = false; 29 | } else if (Character.isWhitespace(current)) { 30 | isPreviousCharSpace = true; 31 | } else { 32 | sb.append(current); 33 | } 34 | } 35 | 36 | return sb.toString(); 37 | } 38 | 39 | @Test 40 | public void testTwoWords() { 41 | assertEquals("TestCase", camelCase("test case")); 42 | } 43 | 44 | @Test 45 | public void testThreeWords() { 46 | assertEquals("CamelCaseMethod", camelCase("camel case method")); 47 | } 48 | 49 | @Test 50 | public void testLeadingSpace() { 51 | assertEquals("CamelCaseWord", camelCase(" camel case word")); 52 | } 53 | 54 | @Test 55 | public void testTrailingSpace() { 56 | assertEquals("SayHello", camelCase("say hello ")); 57 | } 58 | 59 | @Test 60 | public void testSingleLetter() { 61 | assertEquals("Z", camelCase("z")); 62 | } 63 | 64 | @Test 65 | public void testTwoSpacesBetweenWords() { 66 | assertEquals("AbC", camelCase("ab c")); 67 | } 68 | 69 | @Test 70 | public void testEmptyString() { 71 | assertEquals("", camelCase("")); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/kyu6/ConsecutiveFib.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Product of consecutive Fib numbers 5 | * 6 | * https://www.codewars.com/kata/5541f58a944b85ce6d00006a 7 | * 8 | * Details: 9 | * 10 | * The Fibonacci numbers are the numbers in the following integer sequence (Fn): 11 | * 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ... 12 | * 13 | * such as 14 | * F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1. 15 | * 16 | * Given a number, say prod (for product), we search two Fibonacci numbers F(n) and F(n+1) 17 | * verifying 18 | * F(n) * F(n+1) = prod. 19 | * 20 | * Your function productFib takes an integer (prod) and returns an array: 21 | * [F(n), F(n+1), true] or {F(n), F(n+1), 1} or (F(n), F(n+1), True) 22 | * 23 | * depending on the language if 24 | * F(n) * F(n+1) = prod. 25 | * 26 | * If you don't find two consecutive F(m) verifying F(m) * F(m+1) = prod you will return 27 | * [F(m), F(m+1), false] or {F(n), F(n+1), 0} or (F(n), F(n+1), False) 28 | * 29 | * F(m) being the smallest one such as F(m) * F(m+1) > prod. 30 | */ 31 | 32 | public class ConsecutiveFib { 33 | public static long[] productFib(long prod) { 34 | long a = 0; 35 | long b = 1; 36 | 37 | while (a * b <= prod) { 38 | if ((a * b) == prod) { 39 | return new long[]{a, b, 1}; 40 | } 41 | 42 | final long buff = a; 43 | a = b; 44 | b += buff; 45 | } 46 | return new long[]{a, b, 0}; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/kyu6/ConvertStringToCamelCase.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Convert string to camel case 5 | * 6 | * https://www.codewars.com/kata/517abf86da9663f1d2000003 7 | * 8 | * Details: 9 | * 10 | * Complete the method/function so that it converts dash/underscore delimited words into camel 11 | * casing. The first word within the output should be capitalized only if the original word was 12 | * capitalized (known as Upper Camel Case, also often referred to as Pascal case). 13 | */ 14 | 15 | public class ConvertStringToCamelCase { 16 | public static String toCamelCase(String s) { 17 | final String regex = "([^a-zA-Z']+)'*\\1*"; 18 | final String[] split = s.split(regex); 19 | final StringBuilder sb = new StringBuilder(); 20 | 21 | for (int i = 0; i < split.length; i++) { 22 | if (i == 0) { 23 | sb.append(split[i]); 24 | } else if (split[i].length()>0){ 25 | sb.append(split[i].replaceFirst(split[i].substring(0, 1), split[i].substring(0, 1).toUpperCase())); 26 | } 27 | } 28 | return new String(sb); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/kyu6/DigitalRoot.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | /** 3 | * Digital root 4 | * 5 | * https://www.codewars.com/kata/541c8630095125aba6000c00 6 | * 7 | * Details: 8 | * 9 | * Digital root is the recursive sum of all the digits in a number. 10 | * 11 | * Given n, take the sum of the digits of n. If that value has more than one digit, 12 | * continue reducing in this way until a single-digit number is produced. 13 | * This is only applicable to the natural numbers. 14 | */ 15 | 16 | import org.junit.Test; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | 20 | public class DigitalRoot { 21 | public static int digital_root(int n) { 22 | int i = n; 23 | if (i / 10 == 0) { 24 | return i; 25 | } else { 26 | int sum = 0; 27 | while (i > 0) { 28 | sum += i % 10; 29 | i /= 10; 30 | } 31 | return digital_root(sum); 32 | } 33 | } 34 | 35 | @Test 36 | public void tests() { 37 | assertEquals("Nope!", 7, digital_root(16)); 38 | assertEquals("Nope!", 6, digital_root(456)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/kyu6/Dubstep.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Dubstep 5 | * 6 | * https://www.codewars.com/kata/551dc350bf4e526099000ae5 7 | * 8 | * Details: 9 | * 10 | * Polycarpus works as a DJ in the best Berland nightclub, and he often uses dubstep music in his 11 | * performance. Recently, he has decided to take a couple of old songs and make dubstep remixes 12 | * from them. 13 | * 14 | * Let's assume that a song consists of some number of words (that don't contain WUB). To make the 15 | * dubstep remix of this song, Polycarpus inserts a certain number of words "WUB" before the first 16 | * word of the song (the number may be zero), after the last word (the number may be zero), and 17 | * between words (at least one between any pair of neighbouring words), and then the boy glues 18 | * together all the words, including "WUB", in one string and plays the song at the club. 19 | * 20 | * For example, a song with words "I AM X" can transform into a dubstep remix as 21 | * "WUBWUBIWUBAMWUBWUBX" and cannot transform into "WUBWUBIAMWUBX". 22 | * 23 | * Recently, Jonny has heard Polycarpus's new dubstep track, but since he isn't into modern music, 24 | * he decided to find out what was the initial song that Polycarpus remixed. Help Jonny restore 25 | * the original song. 26 | * Input 27 | * 28 | * The input consists of a single non-empty string, consisting only of uppercase English letters, 29 | * the string's length doesn't exceed 200 characters 30 | * Output 31 | * 32 | * Return the words of the initial song that Polycarpus used to make a dubsteb remix. Separate 33 | * the words with a space. 34 | */ 35 | 36 | import org.junit.Test; 37 | 38 | import static org.junit.Assert.assertEquals; 39 | 40 | public class Dubstep { 41 | public static String SongDecoder(String song) { 42 | String s = song; 43 | 44 | s = s.replaceAll("WUB", " ") 45 | .replaceAll("\\s+", " "); 46 | 47 | return s.trim(); 48 | } 49 | 50 | @Test 51 | public void test1() { 52 | assertEquals("ABC", new Dubstep().SongDecoder("WUBWUBABCWUB")); 53 | } 54 | @Test 55 | public void test2() 56 | { 57 | assertEquals("R L", new Dubstep().SongDecoder("RWUBWUBWUBLWUB")); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/kyu6/DuplicateEncoder.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Duplicate Encoder 5 | * 6 | * https://www.codewars.com/kata/54b42f9314d9229fd6000d9c 7 | * 8 | * Details: 9 | * 10 | * The goal of this exercise is to convert a string to a new string where each character in the new 11 | * string is "(" if that character appears only once in the original string, or ")" if that 12 | * character appears more than once in the original string. Ignore capitalization when determining 13 | * if a character is a duplicate. 14 | */ 15 | 16 | import java.util.ArrayList; 17 | import java.util.Collections; 18 | 19 | public class DuplicateEncoder { 20 | public static String encode(String word) { 21 | final ArrayList chars = new ArrayList<>(); 22 | final StringBuilder line = new StringBuilder(); 23 | 24 | for (char c : word.toLowerCase().toCharArray()) { 25 | chars.add(c); 26 | } 27 | 28 | for (int i = 0; i < chars.size(); i++) { 29 | if (Collections.frequency(chars,chars.get(i)) > 1) { 30 | line.append(")"); 31 | } else { 32 | line.append("("); 33 | } 34 | } 35 | 36 | return new String(line); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/kyu6/EncryptThis.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * 6 kyu - Encrypt this! 9 | * 10 | * https://www.codewars.com/kata/5848565e273af816fb000449 11 | * 12 | * Details: 13 | * Encrypt this! 14 | * 15 | * You want to create secret messages which can be deciphered by the Decipher this! 16 | * Here are the conditions: 17 | * 18 | * Your message is a string containing space separated words. 19 | * You need to encrypt each word in the message using the following rules: 20 | * The first letter needs to be converted to its ASCII code. 21 | * The second letter needs to be switched with the last letter 22 | * Keepin' it simple: There are no special characters in input. 23 | */ 24 | 25 | public class EncryptThis { 26 | public static String encryptThis(String text) { 27 | if (text == null || text.isEmpty()) { 28 | return ""; 29 | } 30 | 31 | final String[] words = text.split(" "); 32 | final StringBuilder sb = new StringBuilder(); 33 | 34 | for (String word : words) { 35 | if (!word.isEmpty()) { 36 | final int firstChar = word.charAt(0); 37 | sb.append(firstChar); 38 | 39 | if (word.length() > 3) { 40 | final String helper = word.charAt(word.length() - 1) + 41 | word.substring(2, word.length() - 1) + 42 | word.charAt(1); 43 | sb.append(helper); 44 | } else if (word.length() == 3) { 45 | sb.append(word.charAt(2)); 46 | sb.append(word.charAt(1)); 47 | } else if (word.length() == 2) { 48 | sb.append(word.charAt(1)); 49 | } 50 | 51 | sb.append(" "); 52 | } 53 | } 54 | 55 | sb.setLength(sb.length()-1); 56 | 57 | return new String(sb); 58 | } 59 | 60 | @Test 61 | public void exampleTests() { 62 | assertEquals("", 63 | encryptThis("")); 64 | 65 | assertEquals("65 119esi 111dl 111lw 108dvei 105n 97n 111ka", 66 | encryptThis("A wise old owl lived in an oak")); 67 | 68 | assertEquals("84eh 109ero 104e 115wa 116eh 108sse 104e 115eokp", 69 | encryptThis("The more he saw the less he spoke")); 70 | 71 | assertEquals("84eh 108sse 104e 115eokp 116eh 109ero 104e 104dare", 72 | encryptThis("The less he spoke the more he heard")); 73 | 74 | assertEquals("87yh 99na 119e 110to 97ll 98e 108eki 116tah 119esi 111dl 98dri", 75 | encryptThis("Why can we not all be like that wise old bird")); 76 | 77 | assertEquals("84kanh 121uo 80roti 102ro 97ll 121ruo 104ple", 78 | encryptThis("Thank you Piotr for all your help")); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/kyu6/EnoughIsEnough.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 6 kyu - Delete occurrences of an element if it occurs more than n times 4 | * 5 | * https://www.codewars.com/kata/554ca54ffa7d91b236000023 6 | * 7 | * Details: 8 | * 9 | * Alice and Bob were on a holiday. Both of them took many pictures of the places they've been, and 10 | * now they want to show Charlie their entire collection. However, Charlie doesn't like these 11 | * sessions, since the motive usually repeats. He isn't fond of seeing the Eiffel tower 40 times. 12 | * He tells them that he will only sit during the session if they show the same motive at most N 13 | * times. Luckily, Alice and Bob are able to encode the motive as a number. Can you help them to 14 | * remove numbers such that their list contains each number only up to N times, without changing 15 | * the order? 16 | * Task 17 | * 18 | * Given a list lst and a number N, create a new list that contains each number of lst at most N 19 | * times without reordering. For example if N = 2, and the input is [1,2,3,1,2,1,2,3], you take 20 | * [1,2,3,1,2], drop the next [1,2] since this would lead to 1 and 2 being in the result 3 times, 21 | * and then take 3, which leads to [1,2,3,1,2,3]. 22 | */ 23 | 24 | import java.util.*; 25 | 26 | public class EnoughIsEnough { 27 | public static int[] deleteNth(int[] elements, int maxOccurrences) { 28 | if (elements.length == 0 || maxOccurrences == 0) { 29 | return new int[0]; 30 | } 31 | 32 | final List elemList = new ArrayList<>(elements.length); 33 | final ArrayList filteredElements = new ArrayList<>(); 34 | 35 | for (int e : elements) { 36 | elemList.add(e); 37 | } 38 | 39 | for (int e : elements) { 40 | if (filteredElements.contains(e)) { 41 | final int currentCount = Collections.frequency(filteredElements,e); 42 | 43 | if (currentCount < maxOccurrences) { 44 | filteredElements.add(e); 45 | } 46 | } else { 47 | filteredElements.add(e); 48 | } 49 | } 50 | 51 | int[] result = new int[filteredElements.size()]; 52 | 53 | for (int i = 0; i < filteredElements.size(); i++) { 54 | result[i] = filteredElements.get(i); 55 | } 56 | 57 | return result; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/kyu6/ExtractFileName.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - extract file name 5 | * 6 | * https://www.codewars.com/kata/597770e98b4b340e5b000071 7 | * 8 | * Details: 9 | * 10 | * You have to extract a portion of the file name as follows: 11 | * 12 | * Assume it will start with date represented as long number 13 | * Followed by an underscore 14 | * You'll have then a filename with an extension 15 | * it will always have an extra extension at the end 16 | */ 17 | 18 | import java.util.regex.Matcher; 19 | import java.util.regex.Pattern; 20 | 21 | public class ExtractFileName { 22 | public static String extractFileName(String dirtyFileName) { 23 | final Pattern pattern = Pattern.compile("_(.+)\\."); 24 | final Matcher matcher = pattern.matcher(dirtyFileName); 25 | 26 | matcher.find(); 27 | 28 | return matcher.group(1); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/kyu6/FindOdd.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * https://www.codewars.com/kata/54da5a58ea159efa38000836 5 | * 6 | * Find the odd int 7 | * 8 | * Details: 9 | * 10 | * Given an array, find the integer that appears an odd number of times. 11 | * 12 | * There will always be only one integer that appears an odd number of times. 13 | */ 14 | 15 | import org.junit.Test; 16 | 17 | import java.util.Arrays; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | 22 | public class FindOdd { 23 | public static int findIt(int[] input) { 24 | return Arrays.stream(input) 25 | .distinct() 26 | .filter(a -> Arrays.stream(input) 27 | .filter(b -> a == b).count() % 2 > 0) 28 | .reduce((a, b) -> { 29 | throw new IllegalStateException(); 30 | }) 31 | .getAsInt(); 32 | } 33 | 34 | @Test 35 | public void findTest() { 36 | assertEquals(5, FindOdd.findIt(new int[]{20, 1, -1, 2, -2, 3, 3, 5, 5, 1, 2, 4, 20, 4, -1, -2, 5})); 37 | assertEquals(-1, FindOdd.findIt(new int[]{1, 1, 2, -2, 5, 2, 4, 4, -1, -2, 5})); 38 | assertEquals(5, FindOdd.findIt(new int[]{20, 1, 1, 2, 2, 3, 3, 5, 5, 4, 20, 4, 5})); 39 | assertEquals(10, FindOdd.findIt(new int[]{10})); 40 | assertEquals(10, FindOdd.findIt(new int[]{1, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1})); 41 | assertEquals(1, FindOdd.findIt(new int[]{5, 4, 3, 2, 1, 5, 4, 3, 2, 10, 10})); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/kyu6/FindUniqueNumber.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Find the unique number 5 | * 6 | * https://www.codewars.com/kata/585d7d5adb20cf33cb000235/ 7 | * 8 | * Details: 9 | * 10 | * There is an array with some numbers. All numbers are equal except for one. Try to find it! 11 | * 12 | * It’s guaranteed that array contains at least 3 numbers. 13 | * 14 | * The tests contain some very huge arrays, so think about performance. 15 | */ 16 | 17 | import org.junit.Test; 18 | 19 | import java.util.Arrays; 20 | 21 | import static org.junit.Assert.assertEquals; 22 | 23 | public class FindUniqueNumber { 24 | private double precision = 0.0000000000001; 25 | 26 | public static double findUniq(double arr[]) { 27 | return Arrays.stream(arr) 28 | .distinct() 29 | .filter(a -> Arrays.stream(arr) 30 | .filter(b -> a == b).count() == 1) 31 | .reduce((a, b) -> { 32 | throw new IllegalStateException(); 33 | }) 34 | .getAsDouble(); 35 | } 36 | 37 | @Test 38 | public void sampleTestCases() { 39 | assertEquals(1.0, findUniq(new double[]{0, 1, 0}), precision); 40 | assertEquals(2.0, findUniq(new double[]{1, 1, 1, 2, 1, 1}), precision); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/kyu6/GiveMeADiamond.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Give me a Diamond 5 | * 6 | * https://www.codewars.com/kata/5503013e34137eeeaa001648 7 | * 8 | * Details: 9 | * 10 | * Jamie is a programmer, and James' girlfriend. She likes diamonds, and wants a diamond string 11 | * from James. Since James doesn't know how to make this happen, he needs your help. 12 | * Task 13 | * 14 | * You need to return a string that looks like a diamond shape when printed on the screen, using 15 | * asterisk (*) characters. Trailing spaces should be removed, and every line must be terminated 16 | * with a newline character (\n). 17 | * 18 | * Return null/nil/None/... if the input is an even number or negative, as it is not possible to 19 | * print a diamond of even or negative size. 20 | */ 21 | 22 | public class GiveMeADiamond { 23 | public static final String DIAMOND = "*"; 24 | public static final String SPACE = " "; 25 | 26 | public static String print(int n) { 27 | if (n <= 0 || n % 2 == 0) { 28 | return null; 29 | } else { 30 | final StringBuilder result = new StringBuilder(); 31 | 32 | for (int i = 0; i < n; i++) { 33 | final int spaces = n/2 - i > 0 ? n/2 - i : i - n/2; 34 | final int diamonds = i <= n/2 ? 1+i*2 : -1 + (Math.abs(i - n) << 1); 35 | 36 | if (spaces != 0) { 37 | result.append(String.format(String.format("%%%ds", spaces), " ").replace(" ", SPACE)); 38 | } 39 | 40 | result.append(String.format(String.format("%%%ds", diamonds), " ").replace(" ", DIAMOND)); 41 | result.append("\n"); 42 | } 43 | return new String(result); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/kyu6/IsANumberPrime.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Is a number prime? 5 | * 6 | * https://www.codewars.com/kata/5262119038c0985a5b00029f 7 | * 8 | * Details: 9 | * 10 | * Define a function that takes an integer argument and returns logical value true or false 11 | * depending on if the integer is a prime. 12 | * 13 | * Per Wikipedia, a prime number (or a prime) is a natural number greater than 1 that has no 14 | * positive divisors other than 1 and itself. 15 | */ 16 | 17 | public class IsANumberPrime { 18 | public static boolean isPrime(int num) { 19 | if (num < 2) { 20 | return false; 21 | } else if (num == 2) { 22 | return true; 23 | } else { 24 | final int limit = (int) Math.sqrt(num); 25 | for (int i = 2; i <= limit; i++) { 26 | if (num % i == 0) { 27 | return false; 28 | } 29 | } 30 | } 31 | return true; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/kyu6/MultiplesOf3And5.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Multiples of 3 or 5 5 | * 6 | * https://www.codewars.com/kata/514b92a657cdc65150000006 7 | * 8 | * Details: 9 | * 10 | * If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. 11 | * The sum of these multiples is 23. 12 | * 13 | * Finish the solution so that it returns the sum of all the multiples of 3 or 5 below the number 14 | * passed in. 15 | * 16 | * Note: If the number is a multiple of both 3 and 5, only count it once. 17 | */ 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.stream.IntStream; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | 25 | public class MultiplesOf3And5 { 26 | public static int solution(int number) { 27 | return IntStream.range(1, number) 28 | .filter(n -> n % 3 == 0 || n % 5 == 0) 29 | .sum(); 30 | } 31 | 32 | @Test 33 | public void test() { 34 | assertEquals(1404932684, solution(1000000)); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/kyu6/PersistentBugger.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Persistent Bugger 5 | * 6 | * https://www.codewars.com/kata/55bf01e5a717a0d57e0000ec 7 | * 8 | * Details: 9 | * 10 | * Write a function, persistence, that takes in a positive parameter num and returns its 11 | * multiplicative persistence, which is the number of times you must multiply the digits in num 12 | * until you reach a single digit. 13 | */ 14 | 15 | import org.junit.Assert; 16 | import org.junit.Test; 17 | 18 | public class PersistentBugger { 19 | public static int persistence(final long n) { 20 | return persistenceCount(n, 0); 21 | } 22 | 23 | public static int persistenceCount(long n, int currentCount) { 24 | long l = n; 25 | if (l < 10) { 26 | return currentCount; 27 | } 28 | 29 | long nextN = 1; 30 | while (l != 0) { 31 | nextN *= l % 10; 32 | l /= 10; 33 | } 34 | 35 | return persistenceCount(nextN, ++currentCount); 36 | } 37 | 38 | @Test 39 | public void basicTests() { 40 | System.out.println("****** Basic Tests ******"); 41 | Assert.assertEquals(3, persistence(39)); 42 | Assert.assertEquals(0, persistence(4)); 43 | Assert.assertEquals(2, persistence(25)); 44 | Assert.assertEquals(4, persistence(999)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/kyu6/ReverseWords.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Stop gninnipS My sdroW! 5 | * 6 | * https://www.codewars.com/kata/5264d2b162488dc400000001 7 | * 8 | * Details: 9 | * 10 | * Write a function that takes in a string of one or more words, and returns the same string, but 11 | * with all five or more letter words reversed (Just like the name of this Kata). Strings passed 12 | * in will consist of only letters and spaces. Spaces will be included only when more than one 13 | * word is present. 14 | * 15 | * Examples: spinWords( "Hey fellow warriors" ) => returns "Hey wollef sroirraw" spinWords 16 | * ( "This is a test") => returns "This is a test" spinWords( "This is another test" ) 17 | * => returns "This is rehtona test" 18 | * 19 | */ 20 | 21 | import org.junit.Test; 22 | import static org.junit.Assert.assertEquals; 23 | 24 | public class ReverseWords { 25 | public String spinWords(String sentence) { 26 | final String[] words = sentence.split("\\s+"); 27 | final StringBuilder sb = new StringBuilder(); 28 | 29 | for (String word : words) { 30 | final StringBuilder helper = new StringBuilder(word); 31 | 32 | if (helper.length() >= 5) { 33 | helper.reverse(); 34 | } 35 | 36 | sb.append(helper); 37 | sb.append(" "); 38 | } 39 | 40 | return new String(sb).trim(); 41 | } 42 | 43 | @Test 44 | public void test() { 45 | assertEquals("emocleW", spinWords("Welcome")); 46 | assertEquals("Hey wollef sroirraw", spinWords("Hey fellow warriors")); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/kyu6/TakeATenMinuteWalk.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Take a Ten Minute Walk 5 | * 6 | * https://www.codewars.com/kata/54da539698b8a2ad76000228 7 | * 8 | * Details: 9 | * 10 | * You live in the city of Cartesia where all roads are laid out in a perfect grid. You arrived ten 11 | * minutes too early to an appointment, so you decided to take the opportunity to go for a short 12 | * walk. The city provides its citizens with a Walk Generating App on their phones -- every time 13 | * you press the button it sends you an array of one-letter strings representing directions to 14 | * walk (eg. ['n', 's', 'w', 'e']). You always walk only a single block in a direction and you know 15 | * it takes you one minute to traverse one city block, so create a function that will return true 16 | * if the walk the app gives you will take you exactly ten minutes (you don't want to be early or 17 | * late!) and will, of course, return you to your starting point. Return false otherwise. 18 | * 19 | * Note: you will always receive a valid array containing a random assortment of direction 20 | * letters ('n', 's', 'e', or 'w' only). It will never give you an empty array (that's not 21 | * a walk, that's standing still!). 22 | */ 23 | 24 | public class TakeATenMinuteWalk { 25 | 26 | public static boolean isValid(char[] walk) { 27 | if (walk.length != 10) { 28 | return false; 29 | } 30 | 31 | int x = 0; 32 | int y = 0; 33 | 34 | for (Character c : walk) { 35 | switch (c) { 36 | case 'n': 37 | y++; 38 | break; 39 | case 's': 40 | y--; 41 | break; 42 | case 'e': 43 | x--; 44 | break; 45 | case 'w': 46 | x++; 47 | break; 48 | default : 49 | break; 50 | } 51 | } 52 | 53 | return x == 0 && y == 0; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/kyu6/VasyaClerk.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Vasya Clerk 5 | * 6 | * https://www.codewars.com/kata/555615a77ebc7c2c8a0000b8 7 | * 8 | * Details: 9 | * 10 | * The new "Avengers" movie has just been released! There are a lot of people at the cinema box 11 | * office standing in a huge line. 12 | * Each of them has a single 100, 50 or 25 dollar bill. An "Avengers" ticket costs 25 dollars. 13 | * 14 | * Vasya is currently working as a clerk. He wants to sell a ticket to every single person in this 15 | * line. 16 | * 17 | * Can Vasya sell a ticket to every person and give change if he initially has no money and sells 18 | * the tickets strictly in the order people queue? 19 | * 20 | * Return YES, if Vasya can sell a ticket to every person and give change with the bills he has at 21 | * hand at that moment. Otherwise return NO. 22 | */ 23 | 24 | public class VasyaClerk { 25 | public static final int PRICE = 25; 26 | 27 | public static String Tickets(int[] peopleInLine) { 28 | int countQuarter = 0; 29 | int countFifty = 0; 30 | 31 | for (int i : peopleInLine) { 32 | if (i == PRICE) { 33 | countQuarter++; 34 | } else if (i == 50) { 35 | countQuarter--; 36 | 37 | if (countQuarter < 0) { 38 | return "NO"; 39 | } 40 | 41 | countFifty++; 42 | } else if (i == 100) { 43 | if (countFifty == 0) { 44 | countQuarter -= 3; 45 | } else { 46 | countQuarter--; 47 | countFifty--; 48 | } 49 | if (countQuarter < 0 || countFifty < 0) { 50 | return "NO"; 51 | } 52 | } 53 | } 54 | return "YES"; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/kyu6/WhereIsMyParent.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Where is my parent?!(cry) 5 | * 6 | * https://www.codewars.com/kata/58539230879867a8cd00011c 7 | * 8 | * Details: 9 | * 10 | * Mothers arranged a dance party for the children in school. At that party, there are only mothers 11 | * and their children.All are having great fun on the dance floor when suddenly all the lights went 12 | * out. It's a dark night and no one can see each other. But you were flying nearby and you can see 13 | * in the dark and have ability to teleport people anywhere you want. 14 | * Legend: 15 | * -Uppercase letters stands for mothers, lowercase stand for their children, i.e. "A" mother's 16 | * children are "aaaa". 17 | * -Function input: String contains only letters, uppercase letters are unique. 18 | * 19 | * Task: 20 | * Place all people in alphabetical order where Mothers are followed by their children, i.e. 21 | * "aAbaBb" => "AaaBbb". 22 | */ 23 | 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | 27 | public class WhereIsMyParent { 28 | public static String findChildren(final String text) { 29 | final ArrayList chars = new ArrayList<>(); 30 | 31 | for (Character ch : text.toCharArray()) { 32 | chars.add(ch); 33 | } 34 | 35 | Collections.sort(chars); 36 | 37 | final StringBuilder sb = new StringBuilder(); 38 | 39 | for (int i = 0; i < chars.size(); i++) { 40 | final char currChar = chars.get(i); 41 | final char lowChar = Character.toLowerCase(currChar); 42 | if (lowChar != currChar) { 43 | sb.append(currChar); 44 | 45 | if (chars.get(i) != chars.get(i + 1)) { 46 | final int frequency = Collections.frequency(chars, lowChar); 47 | 48 | if (frequency > 0) { 49 | for (int j = 0; j < frequency; j++) { 50 | sb.append(lowChar); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | return new String(sb); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/kyu6/WhoLikesIt.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu6; 2 | 3 | /** 4 | * 6 kyu - Who likes it? 5 | * 6 | * https://www.codewars.com/kata/5266876b8f4bf2da9b000362 7 | * 8 | * Details: 9 | * 10 | * ou probably know the "like" system from Facebook and other pages. People can "like" blog posts, 11 | * pictures or other items. We want to create the text that should be displayed next to such an 12 | * item. 13 | * 14 | * Implement a function likes :: [String] -> String, which must take in input array, containing the 15 | * names of people who like an item. It must return the display text as shown in the examples 16 | */ 17 | 18 | public class WhoLikesIt { 19 | public static String whoLikesIt(String... names) { 20 | final int len = names.length; 21 | 22 | switch (len) { 23 | case 0: 24 | return "no one likes this"; 25 | case 1: 26 | return String.format("%s likes this", names[0]); 27 | case 2: 28 | return String.format("%s and %s like this", names[0], names[1]); 29 | case 3: 30 | return String.format("%s, %s and %s like this", names[0], names[1], names[2]); 31 | default: 32 | return String.format("%s, %s and %d others like this", names[0], names[1], len-2); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/kyu7/ColouredTriangles.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Coloured Triangles 5 | * 6 | * https://www.codewars.com/kata/5a25ac6ac5e284cfbe000111 7 | * 8 | * Details: 9 | * 10 | * 11 | * If you finish this kata, you can try Insane Coloured Triangles by Bubbler, which is a much 12 | * harder version of this one. 13 | * 14 | * A coloured triangle is created from a row of colours, each of which is red, green or blue. 15 | * Successive rows, each containing one fewer colour than the last, are generated by considering 16 | * the two touching colours in the previous row. If these colours are identical, the same colour 17 | * is used in the new row. If they are different, the missing colour is used in the new row. This 18 | * is continued until the final row, with only a single colour, is generated. 19 | * 20 | * You will be given the first row of the triangle as a string and its your job to return the final 21 | * colour which would appear in the bottom row as a string. In the case of the example above, you 22 | * would the given RRGBRGBB you should return G. 23 | * 24 | * The input string will only contain the uppercase letters R, G, B and there will be at least 25 | * one letter so you do not have to test for invalid input. 26 | * If you are only given one colour as the input, return that colour. 27 | * 28 | * Adapted from the 2017 British Informatics Olympiad 29 | */ 30 | 31 | import org.junit.Test; 32 | import static org.junit.Assert.assertEquals; 33 | 34 | public class ColouredTriangles { 35 | public static char triangle(final String row) { 36 | if (row.length() == 1) return row.charAt(0); 37 | 38 | int currentLength = row.length(); 39 | String previousRow = row; 40 | 41 | 42 | while (currentLength != 1) { 43 | final StringBuilder currentRow = new StringBuilder(); 44 | 45 | for (int i = 0; i < previousRow.length() - 1; i++) { 46 | final char first = previousRow.charAt(i); 47 | final char second = previousRow.charAt(i + 1); 48 | if (first == second) { 49 | currentRow.append(first); 50 | } else currentRow.append(estimateColor(first,second)); 51 | } 52 | 53 | currentLength--; 54 | previousRow = currentRow.toString(); 55 | } 56 | return previousRow.charAt(0); 57 | } 58 | 59 | private static char estimateColor(final char first, final char second) { 60 | boolean isR = first == 'R' || second == 'R'; 61 | boolean isG = first == 'G' || second == 'G'; 62 | 63 | if (!isR) { 64 | return 'R'; 65 | } else if (!isG) { 66 | return 'G'; 67 | } 68 | 69 | return 'B'; 70 | } 71 | 72 | @Test 73 | public void examples() { 74 | // assertEquals("expected", "actual"); 75 | assertEquals('R', triangle("GB")); 76 | assertEquals('R', triangle("RRR")); 77 | assertEquals('B', triangle("RGBG")); 78 | assertEquals('G', triangle("RBRGBRB")); 79 | assertEquals('G', triangle("RBRGBRBGGRRRBGBBBGG")); 80 | assertEquals('B', triangle("B")); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/kyu7/HalvingSum.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Halving Sum 5 | * 6 | * https://www.codewars.com/kata/5a58d46cfd56cb4e8600009d 7 | * 8 | * Details: 9 | * 10 | * Given a positive integer n, calculate the following sum: 11 | * 12 | * n + n/2 + n/4 + n/8 + ... 13 | * 14 | * All elements of the sum are the results of integer division. 15 | */ 16 | 17 | public class HalvingSum { 18 | public int halvingSum(int n) { 19 | return n == 0 ? 0 : n + halvingSum( n / 2); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/kyu7/JadenCasingStrings.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Jaden Case Strings 5 | * 6 | * https://www.codewars.com/kata/5390bac347d09b7da40006f6 7 | * 8 | * Details: 9 | * 10 | * Jaden Smith, the son of Will Smith, is the star of films such as The Karate Kid (2010) and 11 | * After Earth (2013). Jaden is also known for some of his philosophy that he delivers via Twitter. 12 | * When writing on Twitter, he is known for almost always capitalizing every word. For simplicity, 13 | * you'll have to capitalize each word, check out how contractions are expected to be in the 14 | * example below. 15 | * 16 | * Your task is to convert strings to how they would be written by Jaden Smith. 17 | * The strings are actual quotes from Jaden Smith, but they are not capitalized in the same way he 18 | * originally typed them. 19 | * 20 | * Example: 21 | * 22 | * Not Jaden-Cased: "How can mirrors be real if our eyes aren't real" 23 | * Jaden-Cased: "How Can Mirrors Be Real If Our Eyes Aren't Real" 24 | * 25 | * Note that the Java version expects a return value of null for an empty string or null. 26 | */ 27 | 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | 31 | public class JadenCasingStrings { 32 | 33 | public String toJadenCase(String phrase) { 34 | try { 35 | if (phrase.isEmpty()) {return null; 36 | } else { 37 | final List list = new ArrayList<>(); 38 | final StringBuilder a = new StringBuilder(); 39 | 40 | for (int i = 0; i < phrase.length(); i++) { 41 | final char c = phrase.charAt(i); 42 | char d = 0; 43 | 44 | if (i > 1) { 45 | d = phrase.charAt(i - 1); 46 | } 47 | 48 | if (i == 0 || Character.isWhitespace(d)) { 49 | list.add(Character.toUpperCase(c)); 50 | } else { 51 | list.add(c); 52 | } 53 | } 54 | 55 | for (Character character : list) { 56 | a.append(character); 57 | } 58 | 59 | return a.toString(); 60 | } 61 | } 62 | catch (RuntimeException e) { 63 | return null; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/kyu7/LargestFiveDigit.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Largest 5 digit number in a series 5 | * 6 | * https://www.codewars.com/kata/51675d17e0c1bed195000001 7 | * 8 | * Details: 9 | * 10 | * In the following 6 digit number: 11 | * 12 | * 283910 13 | * 14 | * 91 is the greatest sequence of 2 consecutive digits. 15 | * 16 | * In the following 10 digit number: 17 | * 18 | * 1234567890 19 | * 20 | * 67890 is the greatest sequence of 5 consecutive digits. 21 | * 22 | * Complete the solution so that it returns the greatest sequence of five consecutive digits found 23 | * within the number given. The number will be passed in as a string of only digits. It should 24 | * return a five digit integer. The number passed may be as large as 1000 digits. 25 | */ 26 | 27 | public class LargestFiveDigit { 28 | public static int solve(final String digits) { 29 | int result = 0; 30 | 31 | for (int i = 0; i < digits.length() - 4; i++) { 32 | final int compare = Integer.parseInt(digits.substring(i, i+5)); 33 | result = Math.max(result, compare); 34 | } 35 | 36 | return result; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/kyu7/MultiplesOfN.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Return the first M multiples of N 5 | * 6 | * https://www.codewars.com/kata/593c9175933500f33400003e 7 | * 8 | * Details: 9 | * 10 | * Implement a function, multiples(m, n), which returns an array of the first m multiples of the 11 | * real number n. 12 | * Assume that m is a positive integer. 13 | */ 14 | 15 | public class MultiplesOfN { 16 | public static int[] multiples(int m, int n) { 17 | int[] result = new int[m]; 18 | 19 | for (int i = 0; i < m; ) { 20 | result[i] = n * ++i; 21 | } 22 | 23 | return result; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/kyu7/PrinterErrors.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Printer Errors 5 | * 6 | * https://www.codewars.com/kata/56541980fa08ab47a0000040 7 | * 8 | * Details: 9 | * 10 | * In a factory a printer prints labels for boxes. For one kind of boxes the printer has to use 11 | * colors which, for the sake of simplicity, are named with letters from a to m. 12 | * 13 | * The colors used by the printer are recorded in a control string. For example a "good" control 14 | * string would be aaabbbbhaijjjm meaning that the printer used three times color a, four times 15 | * color b, one time color h then one time color a... 16 | * 17 | * Sometimes there are problems: lack of colors, technical malfunction and a "bad" control string 18 | * is produced e.g. aaaxbbbbyyhwawiwjjjwwm with letters not from a to m. 19 | * 20 | * You have to write a function printer_error which given a string will output the error rate of 21 | * the printer as a string representing a rational whose numerator is the number of errors and the 22 | * denominator the length of the control string. Don't reduce this fraction to a simpler expression. 23 | * 24 | * The string has a length greater or equal to one and contains only letters from ato z. 25 | */ 26 | 27 | public class PrinterErrors { 28 | public static String printerError(String s) { 29 | int count = 0; 30 | 31 | for (int i = 0; i < s.length(); i++) { 32 | if ("nopqrstuvwxyz".indexOf(s.charAt(i)) >= 0) { 33 | count++; 34 | } 35 | } 36 | 37 | return String.format("%d/%d", count, s.length()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/kyu7/SplitInParts.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Split In Parts 5 | * 6 | * https://www.codewars.com/kata/5650ab06d11d675371000003 7 | * 8 | * Details: 9 | * 10 | * The aim of this kata is to split a given string into different strings of equal size (note size 11 | * of strings is passed to the method) 12 | */ 13 | 14 | public class SplitInParts { 15 | public static String splitInParts(String s, int partLength) { 16 | final StringBuilder sb = new StringBuilder(); 17 | 18 | for (int i = 0; i <= s.length() - s.length() % partLength - partLength; i += partLength) { 19 | if (i > 0) { 20 | sb.append(" "); 21 | } 22 | sb.append(s, i, i + partLength); 23 | } 24 | 25 | if (s.length() % partLength != 0) { 26 | sb.append(" ") 27 | .append(s.substring(s.length() - s.length()%partLength)); 28 | } 29 | 30 | return new String(sb); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/kyu7/SumOfNumbers.java: -------------------------------------------------------------------------------- 1 | package main.java.kyu7; 2 | 3 | /** 4 | * 7 kyu - Beginner Series #3 Sum of Numbers 5 | * 6 | * https://www.codewars.com/kata/55f2b110f61eb01779000053 7 | * 8 | * Details: 9 | * 10 | * Given two integers a and b, which can be positive or negative, find the sum of all the numbers 11 | * between including them too and return it. If the two numbers are equal return a or b. 12 | * 13 | * Note: a and b are not ordered! 14 | */ 15 | 16 | public class SumOfNumbers { 17 | public int getSum(int a, int b) { 18 | int result = 0; 19 | 20 | for (int i = Math.min(a,b); i <= Math.max(a,b); i++) { 21 | result += i; 22 | } 23 | 24 | return result; 25 | } 26 | } 27 | --------------------------------------------------------------------------------