diff --git a/.DS_Store b/.DS_Store index 3606497c..e34f45a3 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/README.md b/README.md index b9a643c7..0e1e5d22 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,29 @@ -# google-code-jam - -This repository shows reference solutions for several Google Code Jam problems. - -## Table of Contents - -1. [Alien language](solutions/alien-language) -2. [Bathroom stalls](solutions/bathroom-stalls) -3. [Cubic UFO](solutions/cubic-ufo) -4. [Dijkstra](solutions/dijkstra) -5. [Fashion show](solutions/fashion-show) -6. [Go gopher](solutions/go-gopher) -7. [Infinite house of pancakes](solutions/infinite-house-of-pancakes) -8. [Minimum scalar product](solutions/minimum-scalar-product) -9. [Ominous omino](solutions/ominous-omino) -10. [Oversized pancake flipper](solutions/oversized-pancake-flipper) -11. [Reverse words](solutions/reverse-words) -12. [Save the universe](solutions/save-the-universe) -13. [Standing ovation](solutions/standing-ovation) -14. [Store credit](solutions/store-credit) -15. [T9 spelling](solutions/t9-spelling) -16. [Tidy numbers](solutions/tidy-numbers) -17. [Trouble sort](solutions/trouble-sort) +# google-code-jam + +This repository shows reference solutions for several Google Code Jam problems. + +## Table of Contents + +1. [Alien language](solutions/alien-language) +2. [Bathroom stalls](solutions/bathroom-stalls) +3. [Cubic UFO](solutions/cubic-ufo) +4. [Dijkstra](solutions/dijkstra) +5. [Fashion show](solutions/fashion-show) +6. [Go gopher](solutions/go-gopher) +7. [Infinite house of pancakes](solutions/infinite-house-of-pancakes) +8. [Minimum scalar product](solutions/minimum-scalar-product) +9. [Ominous omino](solutions/ominous-omino) +10. [Oversized pancake flipper](solutions/oversized-pancake-flipper) +11. [Reverse words](solutions/reverse-words) +12. [Save the universe](solutions/save-the-universe) +13. [Standing ovation](solutions/standing-ovation) +14. [Store credit](solutions/store-credit) +15. [T9 spelling](solutions/t9-spelling) +16. [Tidy numbers](solutions/tidy-numbers) +17. [Trouble sort](solutions/trouble-sort) +18. [Punched cards](solutions/punched_cards/) +19. [3D Printing](solutions/3DPrinting/) +20. [d1000000](solutions/d1000000/) +21. [Chain reactions](solutions/chain-reactions/) +22. [Twisty Little Passages](solutions/twisty-little-passages/) +23. [Double or One thing](solutions/double-or-one-thing/) diff --git a/solutions/.DS_Store b/solutions/.DS_Store index cce2b293..1e010e55 100644 Binary files a/solutions/.DS_Store and b/solutions/.DS_Store differ diff --git a/solutions/3DPrinting/.DS_Store b/solutions/3DPrinting/.DS_Store new file mode 100644 index 00000000..833148cd Binary files /dev/null and b/solutions/3DPrinting/.DS_Store differ diff --git a/solutions/3DPrinting/Dart/3dprinting.dart b/solutions/3DPrinting/Dart/3dprinting.dart new file mode 100644 index 00000000..4c62b754 --- /dev/null +++ b/solutions/3DPrinting/Dart/3dprinting.dart @@ -0,0 +1,100 @@ +// Google Code Jam doesn't allow `import 'dart:io';`. Now what? :C +import 'dart:io'; +import 'dart:math'; + +int get_input_int() +{ + var my_input = stdin.readLineSync(); + if (my_input != null) + return int.parse(my_input); + else + return 0; +} +String get_input_string() +{ + var my_input = stdin.readLineSync(); + if (my_input != null) + return my_input; + else + return ''; +} + + +List> get_printers_input() +{ + List> printers = []; + for (int j = 0; j < 3; j++) + { + String input_line = get_input_string(); + List input_split = input_line.split(' '); + List input_ints = [ + int.parse(input_split[0]), + int.parse(input_split[1]), + int.parse(input_split[2]), + int.parse(input_split[3]) + ]; + printers.add(input_ints); + } + return printers; +} + + +List give_color_x(List> printers, int color_pos) +{ + return [ + printers[0][color_pos], + printers[1][color_pos], + printers[2][color_pos] + ]; +} + +List return_solution(List> printers) +{ + List my_colors = [0, 0, 0, 0]; + for (int i = 0; i < 4; i++) + { + num min_units = give_color_x(printers, i).cast().reduce(min); + my_colors[i] = min_units.toInt(); + int sum_of_units = my_colors.reduce((a, b) => a + b); + + if (sum_of_units >= 1000000) + { + int difference = sum_of_units - 1000000; + my_colors[i] = my_colors[i] - difference; + return my_colors; + } + } + return my_colors; +} + + +void print_solution(int test_case, List result) +{ + stdout.write('Case #${test_case}: '); + int sum_of_units = result.reduce((a, b) => a + b); + if (sum_of_units == 1000000) + { + for (int i = 0; i < 4; i++) + { + stdout.write(result[i]); + stdout.write(' '); + } + stdout.write('\n'); + } + else + { + print("IMPOSSIBLE"); + } +} + +void main() { + int Times = get_input_int(); + + for (int i = 1; i <= Times; i++) + { + List> my_printers = get_printers_input(); + + List result = return_solution(my_printers); + print_solution(i, result); + } +} diff --git a/solutions/3DPrinting/Kotlin/3dPrinting.kt b/solutions/3DPrinting/Kotlin/3dPrinting.kt new file mode 100644 index 00000000..66351406 --- /dev/null +++ b/solutions/3DPrinting/Kotlin/3dPrinting.kt @@ -0,0 +1,44 @@ +/** +Name: punchedCard.dart +Last update: 18/04/2023 +*/ + +fun main(args: Array) { + val testCases = readln().toInt() + + for (i in 0..testCases) { + + var minC = Int.MAX_VALUE + var minM = Int.MAX_VALUE + var minY = Int.MAX_VALUE + var minK = Int.MAX_VALUE + + for (j in 1..3) { + // Getting the ink amount of each color in the current printer. + val (c, m, y, k) = readln().split(' ').map(String::toInt) + + // Choosing the smallest option. + minC = if (c < minC) c else minC + minM = if (m < minM) m else minM + minY = if (y < minY) y else minY + minK = if (k < minK) k else minK + } + + var totalInk = arrayOf(minC, minM, minY, minK) + + if (totalInk.sum() < 1e6) println("Case #$i: IMPOSSIBLE") + else { + // Using a greedy algorithm to get a combination that fulfills the needed ink. + var neededInk = 1_000_000 + var inkCombination = "Case #$i: " + + for (currentInkAmount in totalInk) { + if(currentInkAmount <= neededInk) inkCombination += "$currentInkAmount " + else if (currentInkAmount > neededInk && neededInk > 0) inkCombination += "$neededInk " + else inkCombination += "0 " + neededInk -= currentInkAmount + } + println(inkCombination) + } + } +} diff --git a/solutions/3DPrinting/Kotlin/main.kt b/solutions/3DPrinting/Kotlin/main.kt new file mode 100644 index 00000000..46510816 --- /dev/null +++ b/solutions/3DPrinting/Kotlin/main.kt @@ -0,0 +1,53 @@ +// kotlinc main.kt -include-runtime -d main.jar && java -jar main.jar 3 300000 200000 300000 500000 300000 200000 500000 300000 300000 500000 300000 200000 1000000 1000000 0 0 0 1000000 1000000 1000000 999999 999999 999999 999999 768763 148041 178147 984173 699508 515362 534729 714381 949704 625054 946212 951187 + +fun main(args: Array) { + val T: Int = args[0].toInt() + var index = 1 + for (test in 0..T - 1) { + var printers: MutableList> = mutableListOf() + for (printer in 0..2) { + var colors: MutableList = mutableListOf() + for (inkValue in 0..3) { + colors.add(args[index].toInt()) + index++ + } + printers.add(colors) + } + print("Case #" + (test + 1) + ":") + solution(printers) + } +} + +fun solution(printers: MutableList>) { + var necessaryInk = 1000000 + var totalInk = 0 + var mins: MutableList = mutableListOf() + for (color in 0..3) { + val arr = arrayOf( + printers[0][color], + printers[1][color], + printers[2][color], + ) + val ints = arr.toList() + totalInk += ints.min() + mins.add(ints.min()) + } + + if (totalInk < necessaryInk) { + println("IMPOSSIBLE") + } else { + var remaining = totalInk - necessaryInk + for (index in 3 downTo 0) { + if (remaining > 0) { + if (mins[index] <= remaining) { + remaining -= mins[index] + mins[index] = 0 + } else { + mins[index] = mins[index] - remaining + remaining = 0 + } + } + } + println(mins) + } +} \ No newline at end of file diff --git a/solutions/3DPrinting/Python/Python3DPrinting.py b/solutions/3DPrinting/Python/Python3DPrinting.py new file mode 100644 index 00000000..22931745 --- /dev/null +++ b/solutions/3DPrinting/Python/Python3DPrinting.py @@ -0,0 +1,38 @@ +def find_color(test_cases, printers): + results = [] + for t in range(test_cases): + min_units = 0 + my_colors = [0, 0, 0, 0] + for i in range(4): + min_units = min(printers[t][0][i], printers[t][1][i], printers[t][2][i]) + + my_colors[i] = min_units + if sum(my_colors) < 10**6: + my_colors[i] = min_units + elif sum(my_colors) >= 10**6: + a = sum(my_colors) - 10**6 + my_colors[i] = my_colors[i] - a + break + + if sum(my_colors) < 10**6: + results.append(["IMPOSSIBLE"]) + else: + results.append(my_colors) + return results + + +def main(): + test_cases = int(input().strip()) + printers = [] + for _ in range(test_cases): + printer_info = [list(map(int, input().split())) for _ in range(3)] + printers.append(printer_info) + + results = find_color(test_cases, printers) + for i, result in enumerate(results): + print(f"Case #{i+1}: ", end='') + print(*result) + + +if __name__ == "__main__": + main() diff --git a/solutions/3DPrinting/README.md b/solutions/3DPrinting/README.md new file mode 100644 index 00000000..11cd03be --- /dev/null +++ b/solutions/3DPrinting/README.md @@ -0,0 +1,16 @@ +# 3D Printing + +## Problem: +You are part of the executive committee of the Database Design Day festivities. You are in charge of promotions and want to print three D's to create a logo of the contest. You can choose any color you want to print them, but all three have to be printed in the same color. + +![](https://codejam.googleapis.com/dashboard/get_file/AQj_6U1yXmbP6Nf5PONAMbqVd5eyM5BBSbjggzDn9H6vS3ATQiqbGVrfZ0ABoAbBkn8IWocYoj1rdJim6VkTTOP4/3d_printing.png) + +You were given three printers and will use each one to print one of the D's. All printers use ink from 4 individual cartridges of different colors (cyan, magenta, yellow, and black) to form any color. For these printers, a color is uniquely defined by 4 non-negative integers c, m, y, and k, which indicate the number of ink units of cyan, magenta, yellow, and black ink (respectively) needed to make the color. + +The total amount of ink needed to print a single D is exactly 10^6 +units. For example, printing a D in pure yellow would use 10^6 units of yellow ink and 0 from all others. Printing a D in the Code Jam red uses 0 units of cyan ink, 500000 units of magenta ink, 450000 units of yellow ink, and 50000 +units of black ink. + +To print a color, a printer must have at least the required amount of ink for each of its 4 color cartridges. Given the number of units of ink each printer has in each cartridge, output any color, defined as 4 non-negative integers that add up to 106, such that all three printers have enough ink to print it. + +More details [here](https://codingcompetitions.withgoogle.com/codejam/round/0000000000876ff1/0000000000a4672b) \ No newline at end of file diff --git a/solutions/3DPrinting/TypeScript/ts3dprinting.ts b/solutions/3DPrinting/TypeScript/ts3dprinting.ts new file mode 100644 index 00000000..970c3945 --- /dev/null +++ b/solutions/3DPrinting/TypeScript/ts3dprinting.ts @@ -0,0 +1,101 @@ +//#region read input input_lines. +declare var require: any; +declare var process: any; + +const readline = require('readline'); + +function read_lines_from_stdin(callback: (input_lines: string[]) => void) { + const input_lines: string[] = []; + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false + }); + + rl.on('line', (input: string) => { + input_lines.push(input); + }); + + rl.on('close', () => { + callback(input_lines); + }); +} +//#endregion + +const logic = (value: string[], tests: number) => { + let test_num: number = 1; + for (let i = 1; test_num <= tests; test_num++) { + + const printer_1: string[] = value[i].split(" "); + const printer_2: string[] = value[++i].split(" "); + const printer_3: string[] = value[++i].split(" "); + i++ + + // Convert the list of strings to a list of numbers these values represent the cyan ink in each printer + // Find the printer with the least cyan ink and store that value in cy + let cy: number = Math.min( + parseInt(printer_1[0]), + parseInt(printer_2[0]), + parseInt(printer_3[0]) + ); + + // Same for all other colors (magenta, yellow and black) to complete CMYK + let ma: number = Math.min( + parseInt(printer_1[1]), + parseInt(printer_2[1]), + parseInt(printer_3[1]) + ); + + let ye: number = Math.min( + parseInt(printer_1[2]), + parseInt(printer_2[2]), + parseInt(printer_3[2]) + ); + + let bl: number = Math.min( + parseInt(printer_1[3]), + parseInt(printer_2[3]), + parseInt(printer_3[3]) + ); + // Put them in an iterable, so they can be added with reduce() + const color_out: number[] = [cy, ma, ye, bl]; + const total_ink: number = color_out.reduce((sum, ink) => sum + ink); + + // If we have less than 10^6 there is not enough ink + if (total_ink < 1000000) { + console.log(`Case #${test_num}: IMPOSSIBLE`); + } + + // If we have just enough ink to print + else if (total_ink === 1000000) { + console.log(`Case #${test_num}: ${cy} ${ma} ${ye} ${bl}`); + } + + // There is more than enough so we need to use less ink + else { + let dif: number = total_ink - 1000000; + + for (let i: number = 0; i < color_out.length; i++) { + if (dif >= color_out[i]) { + dif -= color_out[i]; + color_out[i] = 0; + } else { + color_out[i] -= dif; + break; + } + } + + console.log( + `Case #${test_num}: ${color_out[0]} ${color_out[1]} ${color_out[2]} ${color_out[3]}` + ); + } + } +} + +function main() { + read_lines_from_stdin((input_lines) => { + let tests = parseInt(input_lines[0]); + logic(input_lines, tests) + }) +} +main(); \ No newline at end of file diff --git a/solutions/chain-reactions/.DS_Store b/solutions/chain-reactions/.DS_Store new file mode 100644 index 00000000..01ad4798 Binary files /dev/null and b/solutions/chain-reactions/.DS_Store differ diff --git a/solutions/chain-reactions/Dart/chainedReactions.dart b/solutions/chain-reactions/Dart/chainedReactions.dart new file mode 100644 index 00000000..10f8401f --- /dev/null +++ b/solutions/chain-reactions/Dart/chainedReactions.dart @@ -0,0 +1,53 @@ +import 'dart:io'; +import 'dart:math'; + +void main() { + // Reading the number of tests from input + int testCases = int.parse(stdin.readLineSync() ?? '0'); + + for (int i = 0; i < testCases; i++) { + // Reading the number of modules + int nModules = int.parse(stdin.readLineSync() ?? '0'); + + // Reading module fun + List fun = stdin.readLineSync()?.split(' ').map(int.parse).toList() ?? []; + fun.insert(0, 0); + + // Reading module pointers + List modules = stdin.readLineSync()?.split(' ').map(int.parse).toList() ?? []; + + // Encode the graph adjacencies + List> connections = List.generate(nModules, (_) => []); + for (int j = 0; j < nModules; j++) { + connections[modules[j]].add(j + 1); + } + + int result = 0; + + // Start DFS from inverted graph + for (int v = nModules - 1; v >= 0; v--) { + if (connections[v].isEmpty) { + continue; + } + + int minFun(int a, int b) => (fun[a] < fun[b]) ? a : b; + int u = connections[v].reduce(minFun); + + // Update fun + fun[v] = max(fun[v], fun[u]); + + // Filter out the element 'u' from connections[v] + List filteredNeighbors = connections[v].where((neighbor) => neighbor != u).toList(); + + // Calculate the sum of the values from fun for each filtered neighbor + int sumOfValues = filteredNeighbors.fold(0, (accumulator, neighbor) => accumulator + fun[neighbor]); + + // Update the result by adding the sum of values + result += sumOfValues; + } + + result += fun[0]; + + stdout.write("Case #${i + 1}: ${result}\n"); + } +} diff --git a/solutions/chain-reactions/Kotlin/chain_reactions.kt b/solutions/chain-reactions/Kotlin/chain_reactions.kt new file mode 100644 index 00000000..06fe0bec --- /dev/null +++ b/solutions/chain-reactions/Kotlin/chain_reactions.kt @@ -0,0 +1,41 @@ +import java.util.Scanner +import kotlin.math.* + +fun main() { + val sc = Scanner(System.`in`) + var tests = sc.nextInt() + var i = 1 + while (tests-- > 0) { + var n = sc.nextInt() + var funValue = IntArray(n + 1) + var v = Array(n + 1) { mutableListOf() } + var answer: Long = 0 + + for (i in 1..n) { + funValue[i] = sc.nextInt() + } + + for (i in 1..n) { + var temp = sc.nextInt() + v[temp].add(i) + } + fun dfs(node: Int): Int { + if (v[node].isEmpty()) { + answer += funValue[node] + return funValue[node] + } else { + var minP = Int.MAX_VALUE + for (x in v[node]) { + minP = min(minP, dfs(x)) + } + answer += max(0, funValue[node] - minP) + return max(minP, funValue[node]) + } + } + for (x in v[0]) { + dfs(x) + } + println("Case #$i: $answer") + i++ + } +} \ No newline at end of file diff --git a/solutions/chain-reactions/Python/chainReactions.py b/solutions/chain-reactions/Python/chainReactions.py new file mode 100644 index 00000000..eb72e888 --- /dev/null +++ b/solutions/chain-reactions/Python/chainReactions.py @@ -0,0 +1,203 @@ +from sys import exit + + +class tree(): + def __init__(self, id: int, data: int) -> None: + self.id = id + self.children = [] + self.data = data + + def has_children(self) -> bool: + return len(self.children) != 0 + + def __str__(self, level=0): + result = ("\t" * level) + repr(self.id) + ": " + repr(self.data) + "\n" + + for child in self.children: + result += child.__str__(level + 1) + + return result + + +class chain(): + def __init__(self) -> None: + self.my_machines = [] + self.last_id = 0 + self.pointing_to_void = [] + + def insert_machine(self, points_to: int, fun_factor: int): + new_machine = tree(self.last_id + 1, fun_factor) + self.last_id += 1 + + self.my_machines.append(new_machine) + + if points_to == 0: + self.pointing_to_void.append(new_machine) + else: + try: + self.my_machines[points_to - 1].children.append(new_machine) + except IndexError: + print("Index's out of range. :'(") + print(f"We have {len(self.my_machines)} machines and you tried to point to {points_to}.") + + exit(1) + + def __str__(self) -> str: + result = '' + for machine in self.pointing_to_void: + result += str(machine) + + return result + + +# El código aquí es un ASCO. Es difícil de entender y lo sé. :'( +# Será mucho más fácil que expliquemos cómo funciona en la función +# `DFS_children_old` de abajo. +def DFS_children(machine: tree): + fun_of_dead_branches = [] + pile_fun_to_compare = [(0, [])] + machines_watch_later = [machine] + + while machines_watch_later: + current_machine = machines_watch_later.pop() + + if current_machine is None: + parent_fun, children_fun = pile_fun_to_compare.pop() + lowest_fun = min(children_fun) + children_fun.remove(lowest_fun) + + pile_fun_to_compare[-1][1].append(max( + parent_fun, lowest_fun + )) + for child_fun in children_fun: + fun_of_dead_branches.append(child_fun) + elif current_machine.has_children(): + machines_watch_later.append(None) + for children in current_machine.children: + machines_watch_later.append(children) + + pile_fun_to_compare.append( + (current_machine.data, []) + ) + else: + if not pile_fun_to_compare: + return current_machine.data, [] + + pile_fun_to_compare[-1][1].append(current_machine.data) + + return pile_fun_to_compare[0][1][0] + sum(fun_of_dead_branches) + + +def DFS(my_chain: chain): + current_fun = 0 + + for machine in my_chain.pointing_to_void: + current_fun += DFS_children(machine) + + return current_fun + + +def read_chain_from_input(): + machines = int(input()) # xd + my_chain = chain() + + fun_list = map(int, input().split(' ')) + connections_list = map(int, input().split(' ')) + + for connection, fun in zip(connections_list, fun_list): + my_chain.insert_machine(connection, fun) + + return my_chain + + +def main(): + Times = int(input()) + + for i in range(Times): + my_chain = read_chain_from_input() + print(f"Case #{i + 1}: {DFS(my_chain)}") + +if __name__ == '__main__': + main() + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # INTENTO ANTERIOR FALLIDO. # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +""" +Para entender esto, imaginemos un árbol del siguiente estilo: + 6 + / | \ + 4 2 8 +El nodo de diversión 6 tiene como "hijos" a nodos de diversión 4, 2 y 8. De +entre los hijos, escogeremos al nodo de MENOR diversión. Ése nodo será el que +ejecutaremos primero. Así tendremos la ejecución (2 -> 6 -> Ø) y una diversión +total de 6. ¿Ves por qué tomamos al menor? + +Y no sólo eso. Al tomar al 2, la rama de diversión 4 se quedará con ésa +diversión. Ya no podrá ejecutar nuevamente al 6. A ésta rama del 4 la llamaré +"rama muerta." Exactamente lo mismo pasa con la rama de diversión 8, es una +rama muerta. Al final del código, sumaremos la ejecución del primer nodo junto +con todos los puntos de diversión de las ramas muertas. +""" +def DFS_children_old(current_node: tree): + fun_of_dead_branch = [] + + if len(current_node.children) == 0: + # Si el nodo no tiene hijos, regresamos el valor del nodo. + return current_node.data, fun_of_dead_branch + else: + # De todo nodo, estaremos comparando la diversión de todos sus hijos. + results = [DFS_children(my_child) for my_child in current_node.children] + + # Nuestra meta es encontrar el hijo con la menor diversión. + lowest_fun = 10**10 + id_lowest_fun = -1 + for i, (max_fun, dead_branches) in enumerate(results): + if max_fun < lowest_fun: + id_lowest_fun = i + lowest_fun = max_fun + + # Aprovecharemos para recolectar todas las ramas muertas de los hijos. + fun_of_dead_branch += dead_branches + + # Teniendo ya escogido al hijo con la menor diversión, lo tomaremos + # para compararlo con el padre. Todos los demás hijos se convertirán en + # ramas muertas. (Muajajaja.) + for i in range(len(results)): + if i == id_lowest_fun: + continue + + fun_of_dead_branch.append(results[i][0]) + + # Regresaremos la comparación entre el padre y el hijo con la menor + # diversión, junto con todas las ramas muertas que hemos recolectado. + return max( + current_node.data, + lowest_fun + ), fun_of_dead_branch + + +def DFS_old(my_chain: chain): + current_fun = 0 + + for machine in my_chain.pointing_to_void: + fun_of_child, fun_of_dead_child = DFS_children(machine) + + # Sumaremos primero la diversión de la primera ejecución... + # Creo que éste `max` está de más... Apenas lo vi. + current_fun += max(machine.data, fun_of_child) + # Para después sumar todas las ramas muertas. + current_fun += sum(fun_of_dead_child) + + return current_fun + +"""¿Qué salió mal de ésta implementación? +- La recursividad. (Línea 151.) + +El Test Set 2 lo fallaba por alcanzar el límite de profundidad en cuanto a +recursividad. Aunque sea una solución bonita, no fue suficiente. + +El asqueroso código que está arriba fue mi intento de hacerlo no-recursivo. +Ojalá el código recursivo te haya ayudado a entender qué fue lo que hice. :) +""" diff --git a/solutions/chain-reactions/Python/chainReactionsApproachTwo.py b/solutions/chain-reactions/Python/chainReactionsApproachTwo.py new file mode 100644 index 00000000..61603318 --- /dev/null +++ b/solutions/chain-reactions/Python/chainReactionsApproachTwo.py @@ -0,0 +1,82 @@ +import math +import sys + +sys.setrecursionlimit(10**8) + +output = 0 + +def get_max_fun_factor(module_chain : dict, current_module : int, roots : list): + """Get the max fun function of the current node + + Args: + module_chain: A dictionary, which contains all the modules in the forest. + current_module: The index of the current module + roots: A list, which contains the index of the root nodes (Point to the abyss) + + + Returns: + The max fun factor in the current node. + """ + + # Store the total fun factor in the forest. + global output + + module = module_chain[current_module] + + # Store the max fun factor in the current node + max_fun_factor = module["max_fun_factor"] + + + """ In order to get the max fun fact in the forest, + for each node that has more than 1 children, we're + gonna follow the path with the smaallest one, and + we're gonna add up the others to the total fun factor + in order to increase the sum. + """ + smallest_fun_factor = math.inf + children_fun_factor_sum = 0 + + if not module["children"]: + return max_fun_factor + + for child in module["children"]: + child_fun_factor = get_max_fun_factor(module_chain, child, roots) + children_fun_factor_sum += child_fun_factor + smallest_fun_factor = min(smallest_fun_factor, child_fun_factor) + + output += children_fun_factor_sum - smallest_fun_factor + + module["max_fun_factor"] = max(smallest_fun_factor, max_fun_factor) + max_fun_factor = module["max_fun_factor"] + + return max_fun_factor + + + +if __name__ == "__main__": + test_cases = int(input()) + + for _ in range(test_cases): + modules = int(input()) + fun_factors = [int(x) for x in input().split()] + pointing = [int(x) for x in input().split()] + module_chain = {} + roots = set() + output = 0 + + # Creating the forest structure. + for module in range(modules): + module_chain[module + 1] = { + "fun_factor" : fun_factors[module], + "children" : [], + "max_fun_factor" : fun_factors[module], + } + + if pointing[module] == 0: roots.add(module + 1) + else: module_chain[pointing[module]]["children"].append(module + 1) + + for root in roots: + root_fun_factor = get_max_fun_factor(module_chain, root, roots) + output += root_fun_factor + + print(f"Case #{_ + 1}: {output}") diff --git a/solutions/chain-reactions/TypeScript/main.ts b/solutions/chain-reactions/TypeScript/main.ts new file mode 100644 index 00000000..096250af --- /dev/null +++ b/solutions/chain-reactions/TypeScript/main.ts @@ -0,0 +1,135 @@ +// tsc main.ts && node main.js +function main() { + console.log("Hola"); + + const data = + [ + "1", + "4", + "1 2 3 4", + "0 1 2 2" + ] + /* + [ + "1", + "5", + "1 2 3 2 4", + "0 1 1 3 3" + ] + */ + /* + [ + "3", + "4", + "60 20 40 50", + "0 1 1 2", + "5", + "3 2 1 4 5", + "0 1 1 1 0", + "8", + "100 100 100 90 80 100 90 100", + "0 1 2 1 2 3 1 3", + ] + */ + let tests = parseInt(data[0]); + for (let i = 1; i <= tests * 3; i++) { + solution(data[i], data[++i].split(" "), data[++i].split(" ")); + } +} + +function solution(numElement: string, elementsData: string[], pointingData: string[],) { + // console.log(numElement, elementsData, pointingData); + var mappedData = createData(parseInt(numElement) + 1); + for (let nodo = 0; nodo < elementsData.length; nodo++) { + mappedData[pointingData[nodo]][nodo + 1] = new TreeNode(parseInt(elementsData[nodo])); + //parseInt(elementsData[nodo]); + //new TreeNode(parseInt(elementsData[nodo])); + } + var sum = 0; + for (let pointing = parseInt(numElement); pointing >= 0; pointing--) { + let toAdd: Array = []; + for (let node = parseInt(numElement); node >= 0; node--) { + if (mappedData[pointing][node] != -1) { + //console.log("Actual ", mappedData[pointing][node]); + //console.log("Apuntando a: ", node, pointing); + + // console.log(mappedData[parseInt(pointingData[pointing-1])][pointing]); + if (pointing != 0) { + toAdd.push(mappedData[pointing][node]); + mappedData[parseInt(pointingData[pointing - 1])][pointing].addNode(mappedData[pointing][node]); + if (mappedData[parseInt(pointingData[pointing - 1])][pointing].max < mappedData[pointing][node].max) + mappedData[parseInt(pointingData[pointing - 1])][pointing].max = mappedData[pointing][node].max + // console.log("Apuntando a ", mappedData[parseInt(pointingData[pointing - 1])][pointing]); + } + else { + // console.log(mappedData[pointing][node]); + sum += analizeTree(mappedData[pointing][node]); + } + } + } + if (toAdd.length == 1) { + if (mappedData[parseInt(pointingData[pointing - 1])][pointing].value < toAdd[0].value) { + mappedData[parseInt(pointingData[pointing - 1])][pointing] = toAdd[0]; + } + } + } + console.log("Solucion final: ", sum); +} + +function analizeTree(tree: TreeNode): number { + // console.log("Analizando: ", tree); + let sum = 0; + if (tree.children.length == 0) { + // console.log("Suma hasta el momento", tree.max); + return tree.max; + } else { + let minNode: TreeNode | null = null; + tree.children.forEach(subtree => { + if (minNode == null) { + minNode = subtree; + } else { + console.log("Datos", minNode.max, subtree.max); + + if (minNode.max > subtree.max) { + console.log("Analizando nuevo: ", minNode); + sum += analizeTree(minNode); + minNode = subtree; + } else { + sum += analizeTree(subtree); + } + } + }); + // console.log("El nodo minimo es: ", minNode, sum); + return sum + ((minNode!.max > tree.value) ? minNode!.max : tree.value); + } +} + +function createData(numElem: number) { + var mappedData = new Array>; + for (let x = 0; x < numElem; x++) { + var rowInfo = new Array(); + for (let y = 0; y < numElem; y++) { + rowInfo.push(-1); + } + mappedData.push(rowInfo); + } + return mappedData; +} + +class TreeNode { + public children: Array = []; + public value: number; + public max: number; + public hasMoreChildren: boolean; + + constructor(value: number) { + this.value = value; + this.max = value; + } + + public addNode(node: TreeNode) { + this.children.push(node); + } +} + +main(); \ No newline at end of file diff --git a/solutions/d1000000/.DS_Store b/solutions/d1000000/.DS_Store new file mode 100644 index 00000000..47156555 Binary files /dev/null and b/solutions/d1000000/.DS_Store differ diff --git a/solutions/d1000000/Dart/d1000000.dart b/solutions/d1000000/Dart/d1000000.dart new file mode 100644 index 00000000..699b0bd7 --- /dev/null +++ b/solutions/d1000000/Dart/d1000000.dart @@ -0,0 +1,41 @@ +// this is the suggested approach in the analysis page +// as is this code gives the correct answer but exceeds the time limit +// last updated Wed 19 Apr 15:00 + +// dart:io needs to be imported to read inputs +import 'dart:io'; + +// this function starts at 1 and counts to the highest number possible +// the highest number possible is also the length of the longest straight +int maxStraightLength(list) { + var maxLength = 0; + list.sort(); + + for (int j = 0; j < list.length; j++){ + if (list[j] > maxLength){ + maxLength++; + } + } + return maxLength; +} + +void main() { + // reading number of tests from input + var testS = stdin.readLineSync(); + int testCases = testS != null ? int.parse(testS) : 0; + + for (int i = 0; i < testCases; i++) { + // reading number of dice and their value + var nDiceS = stdin.readLineSync(); + int nDice = nDiceS != null ? int.parse(nDiceS) : 0; + var diceIn = stdin.readLineSync(); + + // converting string to list of strings + List diceS = diceIn != null ? diceIn.split(' ') : []; + // converting list of strings to list of numbers + List dice = diceS.map(int.parse).toList(); + + int res = maxStraightLength(dice); + print("Case #${i + 1}: $res"); + } +} \ No newline at end of file diff --git a/solutions/d1000000/Kotlin/d1000000.kt b/solutions/d1000000/Kotlin/d1000000.kt new file mode 100644 index 00000000..675cb3b7 --- /dev/null +++ b/solutions/d1000000/Kotlin/d1000000.kt @@ -0,0 +1,28 @@ +import java.io.BufferedReader +import java.io.InputStreamReader + +fun maxStraightLength(list: List): Int { + var maxLength = 0 + val sortedList = list.sorted() + + for (j in sortedList.indices) { + if (sortedList[j] > maxLength) { + maxLength++ + } + } + return maxLength +} + +fun main() { + val reader = BufferedReader(InputStreamReader(System.`in`)) + val testCases = reader.readLine().toInt() + + for (i in 1..testCases) { + reader.readLine() // Skip the number of dice input as it's never used + val diceIn = reader.readLine() + + val dice = diceIn.split(" ").map { it.toInt() } + val res = maxStraightLength(dice) + println("Case #$i: $res") + } +} diff --git a/solutions/d1000000/Python/d1000000.py b/solutions/d1000000/Python/d1000000.py new file mode 100644 index 00000000..52f8e4d1 --- /dev/null +++ b/solutions/d1000000/Python/d1000000.py @@ -0,0 +1,33 @@ +""" +Name: d1000000.py +Last update: 18/04/2023 +""" + +import heapq + +def get_used_dice(dice_bucket : list) -> int: + used_dice = 0 + target_die = 1 + # Greedy approach. + while len(dice_bucket) > 0: + current_die = heapq.heappop(dice_bucket) + if current_die >= target_die: + used_dice += 1 + target_die += 1 + + + return used_dice + + +if __name__ == '__main__': + testCases = int(input()) + + for testCase in range(testCases): + dice = int(input()) + # Keep track of the times a n sides die appears. + input_dice = [int(x) for x in input().split(' ')] + # Using a heap to sort the input dice. + heapq.heapify(input_dice) + + used_dice = get_used_dice(input_dice) + print(f'Case #{testCase + 1}: {used_dice}') \ No newline at end of file diff --git a/solutions/d1000000/README.md b/solutions/d1000000/README.md new file mode 100644 index 00000000..b0aeb5c5 --- /dev/null +++ b/solutions/d1000000/README.md @@ -0,0 +1,13 @@ +# d1000000 + +## Problem +While the most typical type of dice have 6 sides, each of which shows a different integer 1 through 6, there are many games that use other types. In particular, a dk is a die with k sides, each of which shows a different integer 1 through k. +A d6 is a typical die, a d4 has four sides, and a d1000000 +has one million sides. + +![](https://codejam.googleapis.com/dashboard/get_file/AQj_6U0Ye6mCUUW3QCOElBYeuWtLh0z2-T88MZ59pc2w5mR7IsB-_p37FxAF3DPKTmFSIgnEgL9yW18R7HPP/D1000000.png) + +In this problem, we start with a collection of N dice. The i-th die is a dSi, that is, it has Si sides showing integers 1 through Si +. A straight of length ℓ starting at x is the list of integers x,x+1,…,x+(ℓ−1). We want to choose some of the dice (possibly all) and pick one number from each to form a straight. What is the longest straight we can form in this way? + +More details [here](https://codingcompetitions.withgoogle.com/codejam/round/0000000000876ff1/0000000000a46471) \ No newline at end of file diff --git a/solutions/d1000000/TypeScript/d1000000.ts b/solutions/d1000000/TypeScript/d1000000.ts new file mode 100644 index 00000000..c809d170 --- /dev/null +++ b/solutions/d1000000/TypeScript/d1000000.ts @@ -0,0 +1,68 @@ +// declare require and process to allow use of readline +declare const require: any; +declare const process: any; + +// import readline library and create interface for reading input +const readline = require('readline'); +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +// define function to calculate maximum straight length given an array of numbers and its length +function maximumStraightLength(S: number[], n: number): number { + + // Sort numerically because default is lexicographical sort: + S.sort((a,b)=>a-b); + + let length = 0; + + // iterate through array to determine maximum straight length + for (let si=0; si length){ + length+=1; + } + } + return length; +} + +// define variable for number of test cases +let t: number; + +// read number of test cases from input and call runTests function +rl.question("", (numTests:string) => { + t = parseInt(numTests); + runTests(); +}); + +// define function to process test cases +function runTests() { + let testCount = 0; + let n = 0; + + // listen for input from readline interface + rl.on("line", (line:string) => { + + // check if all test cases have been processed + if (testCount === t * 2) { + rl.close(); + return; + } + + // if even, input is number of dice + if (testCount % 2 === 0) { + n = parseInt(line); + testCount++; + + // if odd, input is values of dice + } else { + const dice = line.split(" ").map(Number); + const y = maximumStraightLength(dice,n); + const x = Math.floor(testCount / 2) + 1; + + console.log(`Case #${x}: ${y}`); + + testCount++; + } + }); +} diff --git a/solutions/double-or-one-thing/.DS_Store b/solutions/double-or-one-thing/.DS_Store new file mode 100644 index 00000000..c375ac7b Binary files /dev/null and b/solutions/double-or-one-thing/.DS_Store differ diff --git a/solutions/double-or-one-thing/Python/double_or_one_thing.py b/solutions/double-or-one-thing/Python/double_or_one_thing.py new file mode 100644 index 00000000..062f9e7f --- /dev/null +++ b/solutions/double-or-one-thing/Python/double_or_one_thing.py @@ -0,0 +1,73 @@ +""" +Solution to the Double or One thing +from the Round 1A 2022 - Code Jam 2022 + +name: double_or_one_thing.py +problem link: https://codingcompetitions.withgoogle.com/codejam/round/0000000000877ba5/0000000000aa8e9c +""" + +def double_or_one_thing(s:str='')->str: + """Returns the string that comes first alphabetically + from the set of strings that can be produced from s + by highlighting different characters in s. + + Args: + s: A non-empty string. Each character of s is + an uppercase letter from the English alphabet. + + Returns: + The string that comes first alphabetically + from the set of strings that can be produced from + s by highlighting different characters in S. + For example: + CODEJAMDAY -> CCODDEEJAAMDAAY + + Raises: + TypeError: The s contains character that are not from + the English alphabet. + """ + + if not s.isalpha(): + raise TypeError('The string must be non-empty and all the character must be alphabetic.') + + if len(s) == 1: + return s + + output = '' + + current_char = '' + # Store the last character that was processed. + last_char = s[0] + # Store the amount of times the last character processed appeared, + # in case of similar contiguos characters. + char_count = 1 + + for i in range(1, len(s)): + current_char = s[i] + + if ord(current_char) != ord(last_char): + """If the last character(s) is smaller than the current, it appends the + previous character(s) highlighted to create a string lexicographically + smaller, else it only appends the previous character(s) without highlight.""" + output += (last_char * char_count) if ord(last_char) > ord(current_char) \ + else (last_char * (char_count * 2)) + last_char = current_char + char_count = 1 + else: + """Keep the count of how many similar characters have appeared in a row.""" + char_count += 1 + + """Appends the last character(s) that appeared in the string, and it covers the case + all the characters are the same.""" + output += last_char * char_count + + return output.upper() + + +if __name__ == '__main__': + tests = int(input()) + + for i in range(tests): + test_string = input() + test_output = double_or_one_thing(test_string) + print(f'Case #{i+1}: {test_output}') \ No newline at end of file diff --git a/solutions/double-or-one-thing/README.md b/solutions/double-or-one-thing/README.md new file mode 100644 index 00000000..4d92c91c --- /dev/null +++ b/solutions/double-or-one-thing/README.md @@ -0,0 +1,18 @@ +# Double or One thing + +You are given a string of uppercase English letters. You can highlight any number of the letters (possibly all or none of them). The highlighted letters do not need to be consecutive. Then, a new string is produced by processing the letters from left to right: non-highlighted letters are appended once to the new string, while highlighted letters are appended twice. + +Double or One Thing example. + +For example, if the initial string is HELLOWORLD, you could highlight the H, the first and last Ls and the last O to obtain +HELLOWORLD ⇒ HHELLLOWOORLLD. +Similarly, if you highlight nothing, you obtain HELLOWORLD, and if you highlight all of the letters, you obtain HHEELLLLOOWWOORRLLDD. Notice how each occurrence of the same letter can be highlighted independently. + +Given a string, there are multiple strings that can be obtained as a result of this process, depending on the highlighting choices. Among all of those strings, output the one that appears first in alphabetical (also known as lexicographical) order. + +Note: A string s appears before a different string t in alphabetical order if s is a prefix of t or if at the first place s and t differ, +the letter in s is earlier in the alphabet than the letter in t. + +For example, these strings are in alphabetical order: CODE, HELLO, HI, HIM, HOME, JAM. + +More details [here](https://codingcompetitions.withgoogle.com/codejam/round/0000000000877ba5/0000000000aa8e9c) \ No newline at end of file diff --git a/solutions/punched_cards/.DS_Store b/solutions/punched_cards/.DS_Store new file mode 100644 index 00000000..0e0c2237 Binary files /dev/null and b/solutions/punched_cards/.DS_Store differ diff --git a/solutions/punched_cards/Dart/.DS_Store b/solutions/punched_cards/Dart/.DS_Store new file mode 100644 index 00000000..a01c8dce Binary files /dev/null and b/solutions/punched_cards/Dart/.DS_Store differ diff --git a/solutions/punched_cards/Dart/punchedCards.dart b/solutions/punched_cards/Dart/punchedCards.dart new file mode 100644 index 00000000..a00a0b59 --- /dev/null +++ b/solutions/punched_cards/Dart/punchedCards.dart @@ -0,0 +1,67 @@ +/** +Name: punchedCard.dart +Last update: 18/04/2023 +*/ + +import 'dart:io'; + +/// Build a String, which represents the punched card. +/// +/// Throws an [ArgumentError] if the value of [cols] or [rows] +/// is less than 1. Returns the punched card. +String buildPunchedCard(int cols, int rows) { + if (cols < 1 || rows < 1) { + throw ArgumentError.value("The columns and rows must be greater than 0"); + } + + cols = 2 * cols + 1; + rows = 2 * rows + 1; + + String punchedCard = ""; + bool evenRow = false; + bool evenCol = false; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + /// Aligning top row cells + if (i == 0 && j == 0 || + i == 0 && j == 1 || + i == 1 && j == 0 || + i == 1 && j == 1) { + punchedCard += "."; + } else if (evenRow == true && evenCol == true) { + punchedCard += "|"; + } else if (evenRow == true && evenCol == false) { + punchedCard += "."; + } else if (evenRow == false && evenCol == true) { + punchedCard += "-"; + } else { + punchedCard += "+"; + } + evenCol = !evenCol; + } + + punchedCard += "\n"; + evenRow = !evenRow; + } + + return punchedCard; +} + +void main() { + var testCasesS = stdin.readLineSync(); + int testCases = testCasesS != null ? int.parse(testCasesS) : 0; + + for (int i = 0; i < testCases; i++) { + // Getting the punched card size in the current test case. + var rowsS = stdin.readLineSync(); + var colsS = stdin.readLineSync(); + + int cols = colsS != null ? int.parse(colsS) : 0; + int rows = rowsS != null ? int.parse(rowsS) : 0; + + String punchedCard = buildPunchedCard(cols, rows); + + stdout.write("Case #${i + 1}:\n${punchedCard}"); + } +} diff --git a/solutions/punched_cards/Dart/punched_cards.dart b/solutions/punched_cards/Dart/punched_cards.dart new file mode 100644 index 00000000..5bb31baa --- /dev/null +++ b/solutions/punched_cards/Dart/punched_cards.dart @@ -0,0 +1,29 @@ +import 'dart:io'; + +void main(List args) { + int T = int.parse(args[0]); + for (var i = 1; i <= T; i++) { + print("Case #${i}:"); + solution(int.parse(args[(i*2)-1]), int.parse(args[i*2])); + } +} + +void solution(int R, int C) { + for (var j = 0; j <= R * 2; j++) { + bool isEvenJ = j % 2 == 0; + for (var i = 0; i <= C * 2; i++) { + bool isEvenI = i % 2 == 0; + + (i < 2 && j < 2) + ? stdout.write(".") + : isEvenI && isEvenJ + ? stdout.write("+") + : isEvenI && !isEvenJ + ? stdout.write("|") + : !isEvenI && isEvenJ + ? stdout.write("-") + : stdout.write("."); + } + stdout.write("\n"); + } +} diff --git a/solutions/punched_cards/Kotlin/punchedCards.kt b/solutions/punched_cards/Kotlin/punchedCards.kt new file mode 100644 index 00000000..319c41e4 --- /dev/null +++ b/solutions/punched_cards/Kotlin/punchedCards.kt @@ -0,0 +1,24 @@ +fun main(vararg args: String) { + // t number of cases + val t = readLine()!!.toInt() + + for (i in 1..t){ + //r rows, c columns + val (r, c) = readLine()!!.split(' ').map(String::toInt) + println("Case #"+i.toString()+":") + + // print the first row in the punched card + println(".."+"+-".repeat(c-1)+"+") + println(".."+"|.".repeat(c-1)+"|") + + // complete the rest of the punched card according to parity + for (h in 1..2*r-1){ + if (h%2==1){ + println("+-".repeat(c)+"+") + } + else{ + println("|.".repeat(c)+"|") + } + } + } +} diff --git a/solutions/punched_cards/Python/.DS_Store b/solutions/punched_cards/Python/.DS_Store new file mode 100644 index 00000000..6552e3b6 Binary files /dev/null and b/solutions/punched_cards/Python/.DS_Store differ diff --git a/solutions/punched_cards/Python/punchedCards.py b/solutions/punched_cards/Python/punchedCards.py new file mode 100644 index 00000000..111593eb --- /dev/null +++ b/solutions/punched_cards/Python/punchedCards.py @@ -0,0 +1,73 @@ +#define the function used to build the cards +def card_builder(row, col): + + # We create two lists that will serve as our rows + row_a = [] + row_b = [] + + # Special rows that will have elements replaced by dots + row_x = [] + row_y = [] + + i = 0 + + while i <= col: + if i == 0: # To draw the leftmost column + row_a.append("+") + row_b.append("|") + row_x.append("+") + row_y.append("|") + else: # This will draw every other column + row_a.append("-+") + row_b.append(".|") + row_x.append("-+") + row_y.append(".|") + i += 1 + + # Replacing the firs values with dots + row_x[0] = "." + row_x[1] = ".+" + row_x.append("\n") + + row_y[0] = "." + row_y[1] = ".|" + row_y.append("\n") + + # We add line breaks + row_a.append("\n") + row_b.append("\n") + + # We add the first two rows + printable = [] + printable.append("".join(row_x)) + printable.append("".join(row_y)) + + j = 1 # Will keep track of how many rows have been drawn + + while j < row: + printable.append("".join(row_a)) + printable.append("".join(row_b)) + j += 1 + + printable.append("".join(row_a)) # We print this once more to close off cells left open + + return "".join(printable) + + +# Receive the number of tests and use a variable to count them +tests = int(input()) +case = 1 + +# Using a while loop to call the function once for each test +while tests > 0: + current_input = input() + row_col = current_input.split() + + r = int(row_col[0]) + c = int(row_col[1]) + + result = card_builder(r, c) + + print(f"Case #{case}: \n{result}") + case += 1 + tests -= 1 \ No newline at end of file diff --git a/solutions/punched_cards/README.md b/solutions/punched_cards/README.md new file mode 100644 index 00000000..2dbcbad7 --- /dev/null +++ b/solutions/punched_cards/README.md @@ -0,0 +1,23 @@ +# Punched Cards + +## Problem: +A secret team of programmers is plotting to disrupt the programming language landscape and bring punched cards back by introducing a new language called Punched Card Python that lets people code in Python using punched cards! Like good disrupters, they are going to launch a viral campaign to promote their new language before even having the design for a prototype. For the campaign, they want to draw punched cards of different sizes in ASCII art. + +The ASCII art of a punched card they want to draw is similar to an R×C +matrix without the top-left cell. That means, it has (R⋅C)−1 +cells in total. Each cell is drawn in ASCII art as a period (.) surrounded by dashes (-) above and below, pipes (|) to the left and right, and plus signs (+) for each corner. Adjacent cells share the common characters in the border. Periods (.) are used to align the cells in the top row. + +For example, the following is a punched card with R=3 rows and C=4 +columns: + +..+-+-+-+ +..|.|.|.| ++-+-+-+-+ +|.|.|.|.| ++-+-+-+-+ +|.|.|.|.| ++-+-+-+-+ + +There are more examples with other sizes in the samples below. Given the integers R and C describing the size of a punched card, print the ASCII art drawing of it as described above. + +More details [here](https://codingcompetitions.withgoogle.com/codejam/round/0000000000876ff1/0000000000a4621b) \ No newline at end of file diff --git a/solutions/punched_cards/TypeScript/punchedCard.ts b/solutions/punched_cards/TypeScript/punchedCard.ts new file mode 100644 index 00000000..c30cf8a9 --- /dev/null +++ b/solutions/punched_cards/TypeScript/punchedCard.ts @@ -0,0 +1,57 @@ +//#region read input input_lines. DO NOT TOUCH!! +declare var require: any; +declare var process: any; + +const readline = require('readline'); + +function read_lines_from_stdin(callback: (input_lines: string[]) => void) { + const input_lines: string[] = []; + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false + }); + + rl.on('line', (input: string) => { + input_lines.push(input); + }); + + rl.on('close', () => { + callback(input_lines); + }); +} +//#endregion + + +function createRow(prefix: string, middle: string, count: number): string { + return [prefix, ...Array(count + 1).join(middle + ' ').split(' ')].join('') + "\n"; +} + +function cardBuilder(row: number, col: number): string { + const rowA = createRow("+", "-+", col); + const rowB = createRow("|", ".|", col); + const rowX = createRow("..+", "-+", col - 1); + const rowY = createRow(".", ".|", col); + + return [ + rowX, + rowY, + ...Array(row).join(rowA + rowB).split(' '), + rowA.substring(0, rowA.length - 1) + ].join(''); +} + + +//#region Main function. +function main() { + read_lines_from_stdin((input_lines) => { + let Times = parseInt(input_lines[0]); + + for (var i: number = 1; i <= Times; i++) { + let my_nums = input_lines[i].split(' ').map((num) => parseInt(num)); + console.log(`Case #${i}:\n${cardBuilder(my_nums[0], my_nums[1])}`) + } + }) +} +main(); +//#endregion \ No newline at end of file diff --git a/solutions/twisty-little-passages/Dart/twisty_little_passages.dart b/solutions/twisty-little-passages/Dart/twisty_little_passages.dart new file mode 100644 index 00000000..a359e190 --- /dev/null +++ b/solutions/twisty-little-passages/Dart/twisty_little_passages.dart @@ -0,0 +1,50 @@ +import 'dart:io'; +import 'dart:math'; + +void firstTry() { + int testCases = int.parse(stdin.readLineSync()!); + + for (var i = 0; i < testCases; i++) { + List inputList = stdin.readLineSync()!.split(' '); + int nu_rooms = int.parse(inputList[0]); + int nu_actions = int.parse(inputList[1]); + + var rooms_not_seen = List.generate(nu_rooms, (index) => index + 1); + var nu_passages_seen = []; + + inputList = stdin.readLineSync()!.split(' '); + int current_room = int.parse(inputList[0]); + int nu_passages = int.parse(inputList[1]); + + // Borramos el cuarto ya visto y adjuntamos su número de pasillos. + rooms_not_seen.removeAt(current_room - 1); + nu_passages_seen.add(nu_passages); + + // Revolvermos los cuartos y tomamos K cuartos a teletransportarnos. + rooms_not_seen.shuffle(); + rooms_not_seen = + rooms_not_seen.sublist(0, min(nu_actions, rooms_not_seen.length)); + + for (var room in rooms_not_seen) { + stdout.write("T $room"); + + inputList = stdin.readLineSync()!.split(' '); + current_room = int.parse(inputList[0]); + nu_passages = int.parse(inputList[1]); + + nu_passages_seen.add(nu_passages); + } + // Sacamos el promedio de los pasillos y lo multiplicamos por el + // numero real de cuartos y dividimos entre 2, pues cada pasillo + // lo contamos 2 veces. + + var result = + nu_rooms * nu_passages_seen.reduce((value, element) => value + element); + result = result / (2 * nu_passages_seen.length); + stdout.write("E $result"); + } +} + +void main() { + firstTry(); +} diff --git a/solutions/twisty-little-passages/Kotlin/TwistyLittlePassages.kt b/solutions/twisty-little-passages/Kotlin/TwistyLittlePassages.kt new file mode 100644 index 00000000..e75a915d --- /dev/null +++ b/solutions/twisty-little-passages/Kotlin/TwistyLittlePassages.kt @@ -0,0 +1,45 @@ +/** + * Simulates the first strategy to estimate the average number of passages in + * a given set of rooms. + */ +fun first_try() { + // Read the number of test cases from the input. + val test_cases = readLine()!!.toInt() + + // Repeat the simulation for each test case. + repeat(test_cases) { + // Read the number of rooms and number of actions from the input. + val (nu_rooms, nu_actions) = readLine()!!.split(' ').map(String::toInt) + + // Initialize lists for the rooms not seen and the number of passages + // seen, and add the current room and its number of passages to them. + var rooms_not_seen = (1..nu_rooms).toMutableList() + var nu_passages_seen = mutableListOf() + val (current_room, nu_passages) = readLine()!!.split(' ').map(String::toInt) + rooms_not_seen.removeAt(current_room - 1) + nu_passages_seen.add(nu_passages) + + // Randomly choose a subset of the rooms to teleport to, and add their + // number of passages to the list. + rooms_not_seen.shuffle() + rooms_not_seen = rooms_not_seen.take(nu_actions).toMutableList() + for (room in rooms_not_seen) { + // Teleport to the chosen room and read its number of passages. + println("T $room") + val (currentroom, nupassages) = readLine()!!.split(' ').map(String::toInt) + nu_passages_seen.add(nupassages) + } + + // Calculate the estimated average number of passages and print it. + var result = nu_rooms * nu_passages_seen.sum() + result /= (2 * nu_passages_seen.size) + println("E ${result.toInt()}") + } +} + +/** + * Runs the first strategy simulation for each test case. + */ +fun main() { + first_try() +} \ No newline at end of file diff --git a/solutions/twisty-little-passages/Python/twisty_passages.py b/solutions/twisty-little-passages/Python/twisty_passages.py new file mode 100644 index 00000000..4455e36a --- /dev/null +++ b/solutions/twisty-little-passages/Python/twisty_passages.py @@ -0,0 +1,48 @@ +def solution(): + """ + We will teleport to a randomly-chosen subset of the rooms, calculate the + average degree (number of adjoining passages) of those rooms we've visited, + and assume that this is a good estimate of the average degree of all the + rooms. The number of passages is half the sum of the room degrees (since + each passage connects two rooms.) + """ + import random + + test_cases = int(input()) + + for _ in range(test_cases): + nu_rooms, nu_actions = map(int, input().split(' ')) + + rooms_not_seen = list(range(1, nu_rooms + 1)) + nu_passages_seen = [] + + current_room, nu_passages = map(int, input().split(' ')) + + # Remove the current room from the list and append the passages number. + del rooms_not_seen[current_room - 1] + nu_passages_seen.append(nu_passages) + + # Shuffle the rooms list and select the first K rooms. + random.shuffle(rooms_not_seen) + rooms_not_seen = rooms_not_seen[:nu_actions] + + # TP to every room and append the number of passages they have. + for room in rooms_not_seen: + print(f"T {room}") + + current_room, nu_passages = map(int, input().split(' ')) + nu_passages_seen.append(nu_passages) + + # Compute the average of passages for one room + # >>> result = sum(nu_passages_seen) / len(nu_passages_seen), + # multiply it with the total amount of rooms + # >>> result = result * nu_rooms + # and divide by two, because each passage is counted twice + # >>> result = result / 2 + result = nu_rooms * sum(nu_passages_seen) + result = result / (2 * len(nu_passages_seen)) + print(f"E {int(result)}") + + +if __name__ == '__main__': + solution() diff --git a/solutions/twisty-little-passages/README.md b/solutions/twisty-little-passages/README.md new file mode 100644 index 00000000..d451ce1d --- /dev/null +++ b/solutions/twisty-little-passages/README.md @@ -0,0 +1,18 @@ +# Twisty Little Passages + +## Problem + +You are investigating a cave. The cave has N +rooms. There are underground passages that bidirectionally connect some pairs of rooms. Each room has at least one passage connected to it. No passage goes from a room to itself, and no two rooms are connected by more than one passage. + +When in a room, you can identify what room you are in and see how many passages it connects to, but you cannot distinguish the passages. You want to estimate the number of passages that exist in the cave. You are allowed to do up to K operations. An operation is either: be magically teleported to a room of your choice, or +walk through a random passage connected to the room you are in, taking you to the room at the other end of that passage. +When you decide to walk through a passage, you are unable to choose which one, because they are all alike. A passage is chosen for you uniformly at random. + +You begin the investigation in an arbitrary room. Estimate the number of passages between rooms in the cave with at most K operations. + +If E is your estimate and P is the actual number of passages, your solution is considered correct for a test case if and only if P⋅2/3≤E≤P⋅4/3. + +To pass a test set, your solution must be correct for at least 90% of the test cases in that set. + +More details [here](https://codingcompetitions.withgoogle.com/codejam/round/0000000000876ff1/0000000000a45fc0) \ No newline at end of file diff --git a/solutions/twisty-little-passages/TypeScript/twistyLittle.ts b/solutions/twisty-little-passages/TypeScript/twistyLittle.ts new file mode 100644 index 00000000..e696544f --- /dev/null +++ b/solutions/twisty-little-passages/TypeScript/twistyLittle.ts @@ -0,0 +1,48 @@ +// This is a line by line conversion of the python solution for twisty little passages + +declare var require: any; +declare var process: any; +const readline = require('readline'); +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}) +const solve = async () => { + const T = parseInt(await readLine()) + for (let it = 0; it < T; it++) { + const [N, K] = (await readLine()).split(' ').map(Number) + const Rm:any = {} + const E:any = {} + let [r, p] = (await readLine()).split(' ').map(Number) + Rm[r] = p + for (let i = 0; i < K; i++) { + if (i % 2 === 0) { + console.log('W') + let [r, p] = (await readLine()).split(' ').map(Number) + E[r] = p - 0.5 + } else { + const r = Math.random() + console.log(`T ${r}`) + let [p] = (await readLine()).split(' ').map(Number) + Rm[r] = p + } + } + let guess = 0 + for (const r in Rm) { + guess += Rm[r] + } + guess *= N / (2 * Object.keys(Rm).length) + for (const e in E) { + if (!(e in Rm)) { + guess += E[e] / 2 + } + } + console.log(`E ${Math.round(guess)}`) + rl.close() + } +} +const readLine = () => + new Promise(resolve => { + rl.once('line', resolve) + }) +solve() \ No newline at end of file