├── Community Puzzles ├── Sum of divisors.py ├── The Urinal Problem.py ├── Minimal number of swaps.py ├── The experience for creating puzzles.c ├── The Fastest.py ├── May the Triforce be with you.py ├── Simple safecracking.py ├── Gravity.c ├── Simplify Selection Ranges.py ├── Bust speeding vehicles.cs ├── Jack Silver: The Casino Part1.c ├── Brackets, extreme edition.c ├── Snake encoding.py ├── Ancestors & Descendants.cpp ├── Chess cavalry.py ├── Simple fraction to mixed number.c ├── Laser and mirrors.py ├── Bruce Lee.cs ├── ASCII ART : Glass Stacking.c ├── The greatest number.cs ├── CGFunge interpreter.py ├── Maze.cs ├── Text alignment.c └── These Romans are crazy.c ├── Optimization ├── Power of Thor - Code size.js ├── Power of Thor - Code size.py ├── Power of Thor - Code size.cpp ├── The Paranoid Android - Code size.py ├── Code vs Zombies.cpp └── CodinGame Sponsored Contest.py ├── README.md ├── SingePlayer ├── Medium │ ├── ANEO Sponsored Puzzle.py │ ├── Stock Exchange Losses.cpp │ ├── Conway Sequence.cpp │ ├── Dwarfs standing on the shoulders of giants.cpp │ ├── Telephone Numbers.cpp │ ├── Network Cabling.cpp │ ├── Don't Panic - Episode 1.cpp │ ├── Teads Sponsored Challenge.cpp │ ├── There is no Spoon - Episode 1.cpp │ ├── The Gift.cpp │ ├── Scrabble.cpp │ ├── Mayan Calculation.cpp │ ├── Indiana - Level 1.cpp │ ├── Skynet: the Virus.cpp │ ├── Heat Detector.cpp │ ├── Winamax Sponsored Challenge.cpp │ ├── Mars Lander - Level 2.cpp │ └── Bender, a depressed robot.cpp ├── Easy │ ├── Onboarding.cpp │ ├── The River I.cs │ ├── The River II.cs │ ├── Temperatures.cpp │ ├── Horse-racing Duals.sh │ ├── Skynet: the Chasm.cpp │ ├── The Descent.cpp │ ├── ASCII Art.cpp │ ├── What's so complex about mandelbrot.cs │ ├── Chuck Norris.cpp │ ├── Horse-racing Duals.cpp │ ├── MIME Type.cpp │ ├── Mars Lander - Level 1.cpp │ ├── The Travelling Salesman Problem.cs │ ├── Power of Thor.cpp │ ├── Defibrillators.cpp │ ├── Hidden word.cs │ └── Nature of quadrilaterals.cs ├── Hard │ ├── Supercomputer Planning.cpp │ ├── Bender - The Money Machine.cpp │ ├── Genome Sequencing.cpp │ ├── Roller Coaster.cpp │ ├── CGX Formatter.cpp │ ├── Surface.cpp │ ├── Skynet strikes back.cpp │ ├── The Labyrinth.cpp │ ├── Vox Codei.cpp │ ├── Thor VS Giants.cpp │ ├── Skynet: The Bridge.cpp │ ├── Don't Panic - Episode 2.py │ ├── There is no Spoon - Episode 2.py │ └── Winamax Sponsored Contest.cpp └── Very Hard │ ├── The Resistance.cpp │ └── Triangulation.cpp └── Multiplayer Contests └── 2015-11-28 Code vs Zombies.cpp /Community Puzzles/Sum of divisors.py: -------------------------------------------------------------------------------- 1 | n = int(input()) 2 | 3 | sum = 0 4 | for i in range(1, n+1): 5 | sum += (n // i) * i 6 | 7 | print(sum) 8 | -------------------------------------------------------------------------------- /Optimization/Power of Thor - Code size.js: -------------------------------------------------------------------------------- 1 | [x,y,X,Y]=readline().split(' ');for(;;){print((y>Y++?"S":y<--Y?(Y--,"N"):"")+(x>X++?"E":x<--X?(X--,"W"):""))} 2 | -------------------------------------------------------------------------------- /Optimization/Power of Thor - Code size.py: -------------------------------------------------------------------------------- 1 | x,y,X,Y=map(int,input().split()) 2 | while 1:Y,v=(((Y,''),(Y-1,'N'))[yY];X,h=(((X,''),(X-1,'W'))[xX];print(v+h) 3 | -------------------------------------------------------------------------------- /Community Puzzles/The Urinal Problem.py: -------------------------------------------------------------------------------- 1 | n = int(input()) 2 | b = input() 3 | x = max(b.split('!'), key=len) 4 | i = b.index(x) 5 | print(0 if i == 0 else (n-1 if i + len(x) == n else i + len(x)//2)) 6 | -------------------------------------------------------------------------------- /Optimization/Power of Thor - Code size.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #define O(x)std::cout<<(x); 3 | main(){int x,y,X,Y;std::cin>>x>>y>>X>>Y;while(1){O(y>Y?(Y++,"S"):yX?(X++,"E"):xp and d=='LEFT')or(t

= r: 15 | break 16 | if nums[r+1] == '1': 17 | turns += 1 18 | break 19 | 20 | l += 1 21 | 22 | print(turns) 23 | -------------------------------------------------------------------------------- /Community Puzzles/The experience for creating puzzles.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int Level; 9 | scanf("%d", &Level); 10 | int Xp; 11 | scanf("%d", &Xp); 12 | int N; 13 | scanf("%d", &N); 14 | 15 | for (int i = 0; i < N; ++i) { 16 | Xp -= 300; 17 | while (Xp <= 0) { 18 | Level++; 19 | Xp += (int)(Level * sqrt(Level) * 10); 20 | } 21 | } 22 | 23 | printf("%d\n", Level); 24 | printf("%d\n", Xp); 25 | } 26 | -------------------------------------------------------------------------------- /Community Puzzles/The Fastest.py: -------------------------------------------------------------------------------- 1 | minHours = '99' 2 | minMins = '99' 3 | minSecs = '99' 4 | 5 | n = int(input()) 6 | for i in range(n): 7 | t = input() 8 | index = t.find(':') 9 | hours = t[0:index] 10 | index2 = t.find(':', index+1) 11 | mins = t[index+1:index2] 12 | secs = t[index2+1:] 13 | 14 | if hours < minHours or (hours == minHours and mins < minMins) or (hours == minHours and mins == minMins and secs < minSecs): 15 | minHours = hours 16 | minMins = mins 17 | minSecs = secs 18 | 19 | print(str(minHours) + ':' + str(minMins) + ':' + str(minSecs)) 20 | -------------------------------------------------------------------------------- /Community Puzzles/May the Triforce be with you.py: -------------------------------------------------------------------------------- 1 | n = int(input()) 2 | 3 | piramidWidth = 1 + 2*(n-1) 4 | totalWidth = 2*piramidWidth + 1 5 | 6 | print('.' + ' '*(2*(n-1)) + '*') 7 | for i in range(1, n): 8 | starsInRow = 1 + 2*i 9 | spacesBeforeFirstPiramid = (totalWidth - starsInRow) // 2 10 | print(' '*spacesBeforeFirstPiramid + '*'*starsInRow) 11 | 12 | for i in range(n): 13 | starsInRow = 1 + 2*i 14 | spacesBeforeFirstPiramid = (piramidWidth - starsInRow) // 2 15 | spacesBetweenPiramids = 2*spacesBeforeFirstPiramid + 1 16 | print(' '*spacesBeforeFirstPiramid + '*'*starsInRow + ' '*spacesBetweenPiramids + '*'*starsInRow) 17 | -------------------------------------------------------------------------------- /SingePlayer/Medium/ANEO Sponsored Puzzle.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import math 3 | 4 | lights = [] 5 | speed = int(input()) 6 | light_count = int(input()) 7 | for i in range(light_count): 8 | distance, duration = [int(j) for j in input().split()] 9 | lights.append((distance, duration)) 10 | 11 | while speed > 0: 12 | speedMps = speed / 3.6 13 | speedFound = True 14 | for light in lights: 15 | timeToLight = round(light[0] / speedMps, 2) 16 | if (timeToLight // light[1]) % 2 != 0: 17 | speedFound = False 18 | break 19 | 20 | if speedFound: 21 | break 22 | else: 23 | speed -= 1 24 | 25 | print(speed) 26 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Onboarding.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | 15 | // game loop 16 | while (1) { 17 | string enemy1; 18 | cin >> enemy1; cin.ignore(); 19 | int dist1; 20 | cin >> dist1; cin.ignore(); 21 | string enemy2; 22 | cin >> enemy2; cin.ignore(); 23 | int dist2; 24 | cin >> dist2; cin.ignore(); 25 | 26 | if (dist1 < dist2) 27 | cout << enemy1 << endl; 28 | else 29 | cout << enemy2 << endl; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Community Puzzles/Simple safecracking.py: -------------------------------------------------------------------------------- 1 | [letters, words] = input().split(': ') 2 | 3 | def decode(word): 4 | if len(word) == 4 and word[1] == letters[2]: return '0' 5 | if len(word) == 3 and word[0] == letters[18]: return '1' 6 | if len(word) == 3 and word[0] == letters[16]: return '2' 7 | if len(word) == 5 and word[0] == letters[16]: return '3' 8 | if len(word) == 4 and word[1] == letters[18]: return '4' 9 | if len(word) == 4 and word[0] == letters[6]: return '5' 10 | if len(word) == 3 and word[0] == letters[22]: return '6' 11 | if len(word) == 5 and word[0] == letters[22]: return '7' 12 | if len(word) == 5 and word[0] == letters[2]: return '8' 13 | if len(word) == 4 and word[3] == letters[7]: return '9' 14 | 15 | print(''.join(map(decode, words.split('-')))) 16 | -------------------------------------------------------------------------------- /SingePlayer/Easy/The River I.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static long DigitsSum(long n) 11 | { 12 | long sum = 0; 13 | while (n > 0) 14 | { 15 | sum += n % 10; 16 | n /= 10; 17 | } 18 | return sum; 19 | } 20 | 21 | static void Main(string[] args) 22 | { 23 | long r1 = long.Parse(Console.ReadLine()); 24 | long r2 = long.Parse(Console.ReadLine()); 25 | 26 | while (r1 != r2) 27 | { 28 | if (r1 < r2) 29 | r1 = r1 + DigitsSum(r1); 30 | else 31 | r2 = r2 + DigitsSum(r2); 32 | } 33 | 34 | Console.WriteLine(r1); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SingePlayer/Easy/The River II.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static long DigitsSum(long n) 11 | { 12 | long sum = 0; 13 | while (n > 0) 14 | { 15 | sum += n % 10; 16 | n /= 10; 17 | } 18 | return sum; 19 | } 20 | 21 | static void Main(string[] args) 22 | { 23 | long r1 = long.Parse(Console.ReadLine()); 24 | 25 | for (long r2 = r1-1; r2 > 0; --r2) 26 | { 27 | long next = r2 + DigitsSum(r2); 28 | Console.Error.WriteLine(next); 29 | if (next == r1) 30 | { 31 | Console.WriteLine("YES"); 32 | return; 33 | } 34 | } 35 | 36 | Console.WriteLine("NO"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Temperatures.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | /** 11 | * Auto-generated code below aims at helping you parse 12 | * the standard input according to the problem statement. 13 | **/ 14 | int main() 15 | { 16 | int N; // the number of temperatures to analyse 17 | cin >> N; cin.ignore(); 18 | string TEMPS; // the N temperatures expressed as integers ranging from -273 to 5526 19 | getline(cin, TEMPS); 20 | 21 | istringstream iss(TEMPS); 22 | 23 | int min = numeric_limits::max(); 24 | for (int i = 0; i < N; ++i) 25 | { 26 | int nr; 27 | iss >> nr; 28 | 29 | if (abs(nr) <= abs(min)) 30 | min = nr; 31 | } 32 | 33 | if (N > 0) 34 | cout << min << endl; 35 | else 36 | cout << 0 << endl; 37 | } 38 | -------------------------------------------------------------------------------- /Community Puzzles/Gravity.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int width; 8 | int height; 9 | scanf("%d%d", &width, &height); 10 | 11 | char map[height][width+1]; 12 | 13 | for (int i = 0; i < height; i++) { 14 | char line[257]; 15 | scanf("%s", line); 16 | 17 | strcpy(map[i], line); 18 | } 19 | 20 | if (height > 1) { 21 | for (int k = 0; k < height-1; ++k) { 22 | for (int i = 0; i < height-1; ++i) { 23 | for (int j = 0; j < width; ++j) { 24 | if (map[i][j] == '#' && map[i+1][j] == '.') { 25 | map[i+1][j] = '#'; 26 | map[i][j] = '.'; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | 33 | for (int i = 0; i < height; i++) { 34 | printf("%s\n", map[i]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Community Puzzles/Simplify Selection Ranges.py: -------------------------------------------------------------------------------- 1 | numbers = sorted(map(int, input()[1:-1].split(','))) 2 | lastNum = float('inf') 3 | rangeStart = float('inf') 4 | rangeEnd = float('inf') 5 | output = [] 6 | for n in numbers: 7 | if n == lastNum+1: 8 | rangeEnd = n 9 | else: 10 | if rangeStart != float('inf'): 11 | if rangeEnd - rangeStart >= 2: 12 | output.append(str(rangeStart) + '-' + str(lastNum)) 13 | elif rangeEnd - rangeStart == 1: 14 | output.append(str(rangeStart)) 15 | output.append(str(rangeEnd)) 16 | else: 17 | output.append(str(rangeStart)) 18 | 19 | rangeStart = n 20 | rangeEnd = n 21 | 22 | lastNum = n 23 | 24 | if rangeEnd - rangeStart >= 2: 25 | output.append(str(rangeStart) + '-' + str(lastNum)) 26 | elif rangeEnd - rangeStart == 1: 27 | output.append(str(rangeStart)) 28 | output.append(str(rangeEnd)) 29 | else: 30 | output.append(str(rangeStart)) 31 | 32 | print(','.join(output)) 33 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Stock Exchange Losses.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | /** 11 | * Auto-generated code below aims at helping you parse 12 | * the standard input according to the problem statement. 13 | **/ 14 | int main() 15 | { 16 | int n; 17 | cin >> n; cin.ignore(); 18 | string vs; 19 | getline(cin, vs); 20 | 21 | vector values; 22 | stringstream ss(vs); 23 | for (int i = 0; i < n; ++i) 24 | { 25 | string temp; 26 | ss >> temp; 27 | values.push_back(stoi(temp)); 28 | } 29 | 30 | assert(!values.empty()); 31 | 32 | int loss = 0; 33 | int maxSeen = values[0]; 34 | int minSeen = values[0]; 35 | for (int i = 1; i < n; ++i) 36 | { 37 | if (values[i] > maxSeen) 38 | maxSeen = values[i]; 39 | else if (values[i] < minSeen) 40 | { 41 | minSeen = values[i]; 42 | loss = maxSeen - minSeen; 43 | } 44 | } 45 | 46 | cout << -loss << endl; 47 | } 48 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Horse-racing Duals.sh: -------------------------------------------------------------------------------- 1 | maxNr=0 2 | minNr=10000000 3 | minDist=10000000 4 | 5 | read N 6 | P=() 7 | for (( i=0; i 0 )); then 11 | if (( $Pi > $maxNr )); then 12 | dist=$((Pi-maxNr)) 13 | if (( $dist < $minDist )); then 14 | minDist=$dist 15 | fi 16 | maxNr=$Pi 17 | 18 | elif (( $Pi < $minNr )); then 19 | dist=$((minNr-Pi)) 20 | if (( $dist < $minDist )); then 21 | minDist=$dist 22 | fi 23 | minNr=$Pi 24 | 25 | else 26 | for (( j=0; j 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | int R; // the length of the road before the gap. 15 | cin >> R; cin.ignore(); 16 | int G; // the length of the gap. 17 | cin >> G; cin.ignore(); 18 | int L; // the length of the landing platform. 19 | cin >> L; cin.ignore(); 20 | 21 | // game loop 22 | while (1) { 23 | int S; // the motorbike's speed. 24 | cin >> S; cin.ignore(); 25 | int X; // the position on the road of the motorbike. 26 | cin >> X; cin.ignore(); 27 | 28 | if (X >= R + G) 29 | cout << "SLOW" << endl; 30 | else if (X + S > R) 31 | cout << "JUMP" << endl; 32 | else if (S <= G) 33 | cout << "SPEED" << endl; 34 | else if (S > G + 1) 35 | cout << "SLOW" << endl; 36 | else 37 | cout << "WAIT" << endl; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SingePlayer/Easy/The Descent.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | 15 | // game loop 16 | while (1) { 17 | int biggestMH = 0; 18 | int biggestMHPos = 0; 19 | 20 | int SX; 21 | int SY; 22 | cin >> SX >> SY; cin.ignore(); 23 | for (int i = 0; i < 8; i++) { 24 | int MH; // represents the height of one mountain, from 9 to 0. Mountain heights are provided from left to right. 25 | cin >> MH; cin.ignore(); 26 | 27 | if (biggestMH < MH) 28 | { 29 | biggestMH = MH; 30 | biggestMHPos = i; 31 | } 32 | } 33 | 34 | // either: FIRE (ship is firing its phase cannons) or HOLD (ship is not firing). 35 | if (biggestMH != 0 && biggestMHPos == SX) 36 | cout << "FIRE" << endl; 37 | else 38 | cout << "HOLD" << endl; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SingePlayer/Easy/ASCII Art.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | /** 10 | * Auto-generated code below aims at helping you parse 11 | * the standard input according to the problem statement. 12 | **/ 13 | int main() 14 | { 15 | std::map> characters; 16 | 17 | int L; 18 | cin >> L; cin.ignore(); 19 | int H; 20 | cin >> H; cin.ignore(); 21 | string T; 22 | getline(cin, T); 23 | for (int i = 0; i < H; i++) { 24 | string ROW; 25 | getline(cin, ROW); 26 | 27 | characters['?'].push_back(ROW.substr(26*L, L)); 28 | for (int j = 0; j < 26; j++) 29 | characters['A' + j].push_back(ROW.substr(j*L, L)); 30 | } 31 | 32 | for (int i = 0; i < H; i++) 33 | { 34 | for (auto c : T) 35 | { 36 | if ((c >= 'a') && (c <= 'z')) 37 | c += ('A' - 'a'); 38 | else if ((c < 'A') || (c > 'Z')) 39 | c = '?'; 40 | 41 | cout << characters[c][i]; 42 | } 43 | 44 | cout << endl; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SingePlayer/Easy/What's so complex about mandelbrot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static void Main(string[] args) 11 | { 12 | string c = Console.ReadLine(); 13 | int m = int.Parse(Console.ReadLine()); 14 | 15 | int SplitPos = c.LastIndexOf('+'); 16 | if (SplitPos == -1) 17 | SplitPos = c.LastIndexOf('-'); 18 | 19 | float x = float.Parse(c.Substring(0, SplitPos)); 20 | float y = float.Parse(c.Substring(SplitPos, c.Length - SplitPos - 1)); 21 | 22 | float f_real = 0; 23 | float f_im = 0; 24 | for (int i = 0; i < m; ++i) 25 | { 26 | float next_f_real = f_real*f_real - f_im*f_im + x; 27 | float next_f_im = 2*f_real*f_im + y; 28 | f_real = next_f_real; 29 | f_im = next_f_im; 30 | 31 | if (Math.Sqrt(f_real*f_real + f_im*f_im) >= 2) 32 | { 33 | Console.WriteLine(i+1); 34 | return; 35 | } 36 | } 37 | 38 | Console.WriteLine(m); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Community Puzzles/Bust speeding vehicles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static void Main(string[] args) 11 | { 12 | int L = int.Parse(Console.ReadLine()); 13 | int N = int.Parse(Console.ReadLine()); 14 | var Data = new Tuple[N]; 15 | for (int i = 0; i < N; i++) 16 | { 17 | string R = Console.ReadLine(); 18 | var Pieces = R.Split(); 19 | Data[i] = new Tuple(Pieces[0], int.Parse(Pieces[1]), uint.Parse(Pieces[2])); 20 | } 21 | 22 | bool SpeedingFound = false; 23 | for (int i = 1; i < N; i++) 24 | { 25 | var distance = Data[i].Item2 - Data[i-1].Item2; 26 | var duration = (Data[i].Item3 - Data[i-1].Item3) / 3600.0; 27 | 28 | if (distance / duration > L) 29 | { 30 | Console.WriteLine(Data[i].Item1 + " " + Data[i].Item2.ToString()); 31 | SpeedingFound = true; 32 | } 33 | } 34 | 35 | if (!SpeedingFound) 36 | Console.WriteLine("OK"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Community Puzzles/Jack Silver: The Casino Part1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int ROUNDS; 8 | scanf("%d", &ROUNDS); 9 | int CASH; 10 | scanf("%d", &CASH); fgetc(stdin); 11 | for (int i = 0; i < ROUNDS; i++) { 12 | int BET = ceil(CASH / 4.f); 13 | 14 | char PLAY[1025]; 15 | fgets(PLAY, 1025, stdin); 16 | 17 | int BALL = atoi(strtok(PLAY, " ")); 18 | char* CALL = strtok(NULL, " "); 19 | 20 | if (strcmp(CALL, "PLAIN") == 0) 21 | { 22 | int NUMBER = atoi(strtok(NULL, " ")); 23 | if (NUMBER == BALL) { 24 | CASH += 35 * BET; 25 | continue; 26 | } 27 | } 28 | else if (strcmp(CALL, "EVEN\n") == 0) 29 | { 30 | if ((BALL != 0) && (BALL % 2 == 0)) { 31 | CASH += BET; 32 | continue; 33 | } 34 | } 35 | else if (strcmp(CALL, "ODD\n") == 0) 36 | { 37 | if (BALL % 2 != 0) { 38 | CASH += BET; 39 | continue; 40 | } 41 | } 42 | 43 | CASH -= BET; 44 | } 45 | 46 | printf("%d\n", CASH); 47 | } 48 | -------------------------------------------------------------------------------- /Community Puzzles/Brackets, extreme edition.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | char brackets[1024]; 8 | int index = 0; 9 | 10 | char expression[2049]; 11 | scanf("%s", expression); 12 | 13 | int i = 0; 14 | while (expression[i] != 0) { 15 | if (expression[i] == '(' || expression[i] == '[' || expression[i] == '{') { 16 | brackets[index] = expression[i]; 17 | index++; 18 | } 19 | else { 20 | if (expression[i] == ')') { 21 | if (index == 0) { printf("false\n"); return; } 22 | if (brackets[index-1] != '(') { printf("false\n"); return; } 23 | index--; 24 | } 25 | else if (expression[i] == ']') { 26 | if (index == 0) { printf("false\n"); return; } 27 | if (brackets[index-1] != '[') { printf("false\n"); return; } 28 | index--; 29 | } 30 | else if (expression[i] == '}') { 31 | if (index == 0) { printf("false\n"); return; } 32 | if (brackets[index-1] != '{') { printf("false\n"); return; } 33 | index--; 34 | } 35 | } 36 | ++i; 37 | } 38 | 39 | if (index == 0) 40 | printf("true\n"); 41 | else 42 | printf("false\n"); 43 | } 44 | -------------------------------------------------------------------------------- /Community Puzzles/Snake encoding.py: -------------------------------------------------------------------------------- 1 | import sys 2 | square = [] 3 | 4 | n = int(input()) 5 | x = int(input()) 6 | 7 | for i in range(n): 8 | line = input() 9 | square.append([]) 10 | for c in line: 11 | square[-1].append(c) 12 | 13 | def encode(): 14 | x = 0 15 | y = n-1 16 | up = True 17 | tmp = square[y][x] 18 | 19 | while True: 20 | if up: 21 | if y == 0: 22 | if x+1 == n: 23 | square[n-1][0] = tmp 24 | return 25 | else: 26 | tmp,square[y][x+1] = square[y][x+1],tmp 27 | x += 1 28 | up = False 29 | else: 30 | tmp,square[y-1][x] = square[y-1][x],tmp 31 | y -= 1 32 | else: 33 | if y == n-1: 34 | if x+1 == n: 35 | square[n-1][0] = tmp 36 | return 37 | else: 38 | tmp,square[y][x+1] = square[y][x+1],tmp 39 | x += 1 40 | up = True 41 | else: 42 | tmp,square[y+1][x] = square[y+1][x],tmp 43 | y += 1 44 | 45 | 46 | 47 | 48 | for i in range(x): 49 | encode() 50 | 51 | for r in range(n): 52 | for c in range(n): 53 | print(square[r][c], end='') 54 | print('') 55 | 56 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Chuck Norris.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | string MESSAGE; 15 | getline(cin, MESSAGE); 16 | 17 | // Generate the binary representation of the message 18 | string bitMessage; 19 | for (char c : MESSAGE) 20 | { 21 | for (int i = 0; i < 7; ++i) 22 | { 23 | c = c << 1; 24 | bitMessage += ((c >> 7) & 1) + '0'; 25 | } 26 | } 27 | 28 | // Encode the message 29 | int i = 0; 30 | while (i < bitMessage.size()) 31 | { 32 | if (bitMessage[i] == '0') 33 | { 34 | cout << "00 "; 35 | for (; i < bitMessage.size() && bitMessage[i] == '0'; ++i) 36 | cout << "0"; 37 | 38 | if (i < bitMessage.size()) 39 | cout << " "; 40 | } 41 | else 42 | { 43 | cout << "0 "; 44 | for (; i < bitMessage.size() && bitMessage[i] == '1'; ++i) 45 | cout << "0"; 46 | 47 | if (i < bitMessage.size()) 48 | cout << " "; 49 | } 50 | } 51 | 52 | cout << endl; 53 | } 54 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Horse-racing Duals.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | vector P; 15 | int minDist = 10000000; 16 | 17 | int maxNr = 0; 18 | int minNr = 10000000; 19 | 20 | int N; 21 | cin >> N; cin.ignore(); 22 | for (int i = 0; i < N; i++) { 23 | int Pi; 24 | cin >> Pi; cin.ignore(); 25 | 26 | if (Pi > maxNr) 27 | { 28 | int dist = Pi - maxNr; 29 | if (dist < minDist) 30 | minDist = dist; 31 | 32 | maxNr = Pi; 33 | } 34 | else if (Pi < minNr) 35 | { 36 | int dist = minNr - Pi; 37 | if (dist < minDist) 38 | minDist = dist; 39 | 40 | minNr = Pi; 41 | } 42 | else 43 | { 44 | for (int j = 0; j < i; ++j) 45 | { 46 | int dist = abs(P[j] - Pi); 47 | if (dist < minDist) 48 | minDist = dist; 49 | } 50 | } 51 | 52 | P.push_back(Pi); 53 | } 54 | 55 | cout << minDist << endl; 56 | } 57 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Supercomputer Planning.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int main() 10 | { 11 | map tasks; 12 | 13 | int N; 14 | cin >> N; cin.ignore(); 15 | for (int i = 0; i < N; i++) { 16 | int J; 17 | int D; 18 | cin >> J >> D; cin.ignore(); 19 | 20 | // When two tasks start at the same moment, forget about the larger task 21 | if ((tasks.find(J) == tasks.end()) || (tasks[J] > D)) 22 | tasks[J] = D; 23 | } 24 | 25 | if (tasks.empty()) 26 | cout << 0 << endl; 27 | else 28 | { 29 | unsigned int nrOfTasks = 0; 30 | unsigned int taskEnd = 0; 31 | for (auto& task : tasks) 32 | { 33 | // If we can just take this task then do so 34 | if (task.first >= taskEnd) 35 | { 36 | nrOfTasks++; 37 | taskEnd = task.first + task.second; 38 | } 39 | else // Overlap 40 | { 41 | // If the next task ends before the old one then use it instead 42 | if (task.first + task.second < taskEnd) 43 | taskEnd = task.first + task.second; 44 | } 45 | } 46 | 47 | cout << nrOfTasks << endl; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SingePlayer/Easy/MIME Type.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | /** 10 | * Auto-generated code below aims at helping you parse 11 | * the standard input according to the problem statement. 12 | **/ 13 | int main() 14 | { 15 | map extMap; 16 | 17 | int N; // Number of elements which make up the association table. 18 | cin >> N; cin.ignore(); 19 | int Q; // Number Q of file names to be analyzed. 20 | cin >> Q; cin.ignore(); 21 | for (int i = 0; i < N; i++) { 22 | string EXT; // file extension 23 | string MT; // MIME type. 24 | cin >> EXT >> MT; cin.ignore(); 25 | 26 | transform(EXT.begin(), EXT.end(), EXT.begin(), ::tolower); 27 | extMap[EXT] = MT; 28 | } 29 | for (int i = 0; i < Q; i++) { 30 | string FNAME; // One file name per line. 31 | getline(cin, FNAME); 32 | 33 | auto pos = FNAME.rfind('.'); 34 | if (pos == string::npos) 35 | cout << "UNKNOWN" << endl; 36 | else 37 | { 38 | string EXT = FNAME.substr(pos + 1); 39 | transform(EXT.begin(), EXT.end(), EXT.begin(), ::tolower); 40 | 41 | if (extMap.find(EXT) != extMap.end()) 42 | cout << extMap[EXT] << endl; 43 | else 44 | cout << "UNKNOWN" << endl; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Conway Sequence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | /** 10 | * Auto-generated code below aims at helping you parse 11 | * the standard input according to the problem statement. 12 | **/ 13 | int main() 14 | { 15 | int R; 16 | cin >> R; cin.ignore(); 17 | int L; 18 | cin >> L; cin.ignore(); 19 | 20 | vector> lines(2, vector(1, R)); 21 | for (int l = 2; l <= L; ++l) 22 | { 23 | assert(!lines[l-1].empty()); 24 | int last = numeric_limits::max(); 25 | vector> count; 26 | for (int i = 0; i < lines[l-1].size(); ++i) 27 | { 28 | if (lines[l-1][i] == last) 29 | { 30 | count.back().second++; 31 | } 32 | else 33 | { 34 | last = lines[l-1][i]; 35 | count.push_back({lines[l-1][i], 1}); 36 | } 37 | } 38 | 39 | lines.push_back({}); 40 | for (int i = 0; i < count.size(); ++i) 41 | { 42 | lines[l].push_back(count[i].second); 43 | lines[l].push_back(count[i].first); 44 | } 45 | } 46 | 47 | for (int i = 0; i < lines.back().size(); ++i) 48 | { 49 | if (i+1 == lines.back().size()) 50 | cout << lines.back()[i] << endl; 51 | else 52 | cout << lines.back()[i] << " "; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Community Puzzles/Ancestors & Descendants.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | std::vector descendants; 11 | 12 | int count; 13 | cin >> count; cin.ignore(); 14 | for (int i = 0; i < count; i++) { 15 | string line; 16 | getline(cin, line); 17 | 18 | auto dots = line.rfind('.'); 19 | if (dots == std::string::npos) 20 | dots = 0; 21 | else 22 | dots++; 23 | std::cerr << line << std::endl; 24 | if (descendants.size() <= dots) 25 | { 26 | descendants.push_back(line.substr(dots)); 27 | } 28 | else 29 | { 30 | if (!descendants.empty()) 31 | { 32 | std::cout << descendants[0]; 33 | for (unsigned int j = 1; j < descendants.size(); ++j) 34 | std::cout << " > " << descendants[j]; 35 | 36 | std::cout << std::endl; 37 | } 38 | 39 | descendants.erase(descendants.begin()+dots, descendants.end()); 40 | descendants.push_back(line.substr(dots)); 41 | } 42 | } 43 | 44 | if (!descendants.empty()) 45 | { 46 | std::cout << descendants[0]; 47 | for (unsigned int j = 1; j < descendants.size(); ++j) 48 | std::cout << " > " << descendants[j]; 49 | 50 | std::cout << std::endl; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Dwarfs standing on the shoulders of giants.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int count(int node, map>& edges) 11 | { 12 | if (!edges[node].empty()) 13 | { 14 | int maxCount = 1; 15 | for (int v : edges[node]) 16 | { 17 | int c = count(v, edges); 18 | if (c > maxCount) 19 | maxCount = c; 20 | } 21 | 22 | return maxCount + 1; 23 | } 24 | else 25 | return 1; 26 | } 27 | 28 | int main() 29 | { 30 | set roots; 31 | map> edges; 32 | 33 | int n; // the number of relationships of influence 34 | cin >> n; cin.ignore(); 35 | for (int i = 0; i < n; i++) { 36 | int x; // a relationship of influence between two people (x influences y) 37 | int y; 38 | cin >> x >> y; cin.ignore(); 39 | 40 | // Add the relationship to the list 41 | edges[x].push_back(y); 42 | roots.insert(x); 43 | } 44 | 45 | // Find all the roots 46 | for (auto& vs : edges) 47 | { 48 | for (int v : vs.second) 49 | roots.erase(v); 50 | } 51 | 52 | // Start from all roots and count their influences 53 | int maxCount = 0; 54 | for (int v : roots) 55 | { 56 | int c = count(v, edges); 57 | if (c > maxCount) 58 | maxCount = c; 59 | } 60 | 61 | cout << maxCount << endl; 62 | } 63 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Telephone Numbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct Node 10 | { 11 | char value; 12 | vector> children; 13 | }; 14 | 15 | void insert(shared_ptr root, string telephone) 16 | { 17 | if (telephone.empty()) 18 | return; 19 | 20 | // Recursively pass it to our children if numbers have been seen before 21 | for (auto& child : root->children) 22 | { 23 | if (child->value == telephone[0]) 24 | { 25 | insert(child, telephone.substr(1, telephone.length()-1)); 26 | return; 27 | } 28 | } 29 | 30 | // A new number is found on this position, create a new branch 31 | shared_ptr child = make_shared(); 32 | child->value = telephone[0]; 33 | insert(child, telephone.substr(1, telephone.length()-1)); 34 | root->children.push_back(child); 35 | } 36 | 37 | int count(shared_ptr root) 38 | { 39 | int c = 1; 40 | for (auto& child : root->children) 41 | c += count(child); 42 | 43 | return c; 44 | } 45 | 46 | int main() 47 | { 48 | shared_ptr root = make_shared(); 49 | root->value = numeric_limits::max(); // undefined (we don't need to use the root node, only to store our tree) 50 | 51 | int N; 52 | cin >> N; cin.ignore(); 53 | for (int i = 0; i < N; i++) { 54 | string telephone; 55 | cin >> telephone; cin.ignore(); 56 | 57 | insert(root, telephone); 58 | } 59 | 60 | cout << count(root)-1 << endl; 61 | } 62 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Network Cabling.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | vector> positions; 15 | 16 | int N; 17 | cin >> N; cin.ignore(); 18 | for (int i = 0; i < N; i++) { 19 | int X; 20 | int Y; 21 | cin >> X >> Y; cin.ignore(); 22 | 23 | positions.push_back({X, Y}); 24 | } 25 | 26 | // Calculate the median y position 27 | sort(positions.begin(), positions.end(), [](pair p1, pair p2){ return p1.second < p2.second; }); 28 | int mainCableY; 29 | if (positions.size() % 2) 30 | mainCableY = positions[positions.size() / 2].second; 31 | else 32 | mainCableY = (positions[(positions.size() / 2)-1].second + positions[positions.size() / 2].second) / 2; 33 | 34 | // Calculate the length of the main cable 35 | int minPosX = numeric_limits::max(); 36 | int maxPosX = numeric_limits::min(); 37 | for (auto& pos : positions) 38 | { 39 | if (pos.first < minPosX) 40 | minPosX = pos.first; 41 | if (pos.first > maxPosX) 42 | maxPosX = pos.first; 43 | } 44 | 45 | int mainCableLength = maxPosX - minPosX; 46 | 47 | // Calculate the total length of the cables 48 | long long totalLength = mainCableLength; 49 | for (auto& pos : positions) 50 | totalLength += abs(mainCableY - pos.second); 51 | 52 | cout << totalLength << endl; 53 | } 54 | -------------------------------------------------------------------------------- /Community Puzzles/Chess cavalry.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import math 3 | 4 | grid = [] 5 | 6 | w, h = [int(i) for i in raw_input().split()] 7 | for i in xrange(h): 8 | grid.append(raw_input()) 9 | 10 | def addMove(moves, pos): 11 | if grid[pos[1]][pos[0]] != '#': 12 | moves.append(pos) 13 | 14 | def getLegalMoves(pos): 15 | moves = [] 16 | if pos[0] >= 2: 17 | if pos[1] >= 1: 18 | addMove(moves, (pos[0]-2, pos[1]-1)) 19 | if pos[1] < h-1: 20 | addMove(moves, (pos[0]-2, pos[1]+1)) 21 | if pos[0] < w-2: 22 | if pos[1] >= 1: 23 | addMove(moves, (pos[0]+2, pos[1]-1)) 24 | if pos[1] < h-1: 25 | addMove(moves, (pos[0]+2, pos[1]+1)) 26 | if pos[1] >= 2: 27 | if pos[0] >= 1: 28 | addMove(moves, (pos[0]-1, pos[1]-2)) 29 | if pos[0] < w-1: 30 | addMove(moves, (pos[0]+1, pos[1]-2)) 31 | if pos[1] < h-2: 32 | if pos[0] >= 1: 33 | addMove(moves, (pos[0]-1, pos[1]+2)) 34 | if pos[0] < w-1: 35 | addMove(moves, (pos[0]+1, pos[1]+2)) 36 | return moves 37 | 38 | startPos = (0,0) 39 | for r in range(h): 40 | for c in range(w): 41 | if grid[r][c] == 'B': 42 | startPos = (c,r) 43 | 44 | visited = [] 45 | fringe = [] # queue 46 | fringe.append((startPos, 0)) 47 | while len(fringe) > 0: 48 | node = fringe.pop(0) 49 | 50 | if node[0] in visited: 51 | continue 52 | 53 | visited += [node[0]] 54 | 55 | if grid[node[0][1]][node[0][0]] == 'E': 56 | print node[1] 57 | quit() 58 | else: 59 | successors = getLegalMoves(node[0]) 60 | for successor in successors: 61 | fringe.append((successor, node[1]+1)) 62 | 63 | print "Impossible" 64 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Don't Panic - Episode 1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int main() 10 | { 11 | int nbFloors; // number of floors 12 | int width; // width of the area 13 | int nbRounds; // maximum number of rounds 14 | int exitFloor; // floor on which the exit is found 15 | int exitPos; // position of the exit on its floor 16 | int nbTotalClones; // number of generated clones 17 | int nbAdditionalElevators; // ignore (always zero) 18 | int nbElevators; // number of elevators 19 | cin >> nbFloors >> width >> nbRounds >> exitFloor >> exitPos >> nbTotalClones >> nbAdditionalElevators >> nbElevators; cin.ignore(); 20 | map elevators; 21 | for (int i = 0; i < nbElevators; i++) { 22 | int elevatorFloor; // floor on which this elevator is found 23 | int elevatorPos; // position of the elevator on its floor 24 | cin >> elevatorFloor >> elevatorPos; cin.ignore(); 25 | elevators[elevatorFloor] = elevatorPos; 26 | } 27 | 28 | // game loop 29 | while (1) { 30 | int cloneFloor; // floor of the leading clone 31 | int clonePos; // position of the leading clone on its floor 32 | string direction; // direction of the leading clone: LEFT or RIGHT 33 | cin >> cloneFloor >> clonePos >> direction; cin.ignore(); 34 | 35 | int targetPos; 36 | if (cloneFloor == exitFloor) 37 | targetPos = exitPos; 38 | else 39 | targetPos = elevators[cloneFloor]; 40 | 41 | if ((targetPos > clonePos && direction == "LEFT") 42 | ||(targetPos < clonePos && direction == "RIGHT")) 43 | cout << "BLOCK" << endl; 44 | else 45 | cout << "WAIT" << endl; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Teads Sponsored Challenge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int dfs(map>& graph, int start) 11 | { 12 | stack> fringe; 13 | fringe.push(tuple{start, start, 0}); 14 | 15 | int maxDistance = 0; 16 | while (!fringe.empty()) 17 | { 18 | int nextVertex = get<0>(fringe.top()); 19 | int parent = get<1>(fringe.top()); 20 | int distance = get<2>(fringe.top()); 21 | fringe.pop(); 22 | 23 | if (distance > maxDistance) 24 | maxDistance = distance; 25 | 26 | for (int vertex : graph[nextVertex]) 27 | { 28 | if (vertex != parent) 29 | fringe.push(tuple{vertex, nextVertex, distance+1}); 30 | } 31 | } 32 | 33 | return maxDistance + 1; 34 | } 35 | 36 | int main() 37 | { 38 | map> graph; 39 | 40 | int n; // the number of adjacency relations 41 | cin >> n; cin.ignore(); 42 | for (int i = 0; i < n; i++) { 43 | int xi; // the ID of a person which is adjacent to yi 44 | int yi; // the ID of a person which is adjacent to xi 45 | cin >> xi >> yi; cin.ignore(); 46 | 47 | graph[xi].push_back(yi); 48 | graph[yi].push_back(xi); 49 | } 50 | 51 | // Find a leaf node 52 | int leafVertex; 53 | for (auto& vertex : graph) 54 | { 55 | if (vertex.second.size() == 1) 56 | { 57 | leafVertex = vertex.first; 58 | break; 59 | } 60 | } 61 | 62 | // Distance between furthest node and leaf node divided by 2 is what we need 63 | int distance = dfs(graph, leafVertex); 64 | cout << (distance / 2) << endl; 65 | } 66 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Mars Lander - Level 1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | int N; // the number of points used to draw the surface of Mars. 15 | cin >> N; cin.ignore(); 16 | for (int i = 0; i < N; i++) { 17 | int LAND_X; // X coordinate of a surface point. (0 to 6999) 18 | int LAND_Y; // Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars. 19 | cin >> LAND_X >> LAND_Y; cin.ignore(); 20 | } 21 | 22 | int VSold = 0; 23 | 24 | // game loop 25 | while (1) { 26 | int X; 27 | int Y; 28 | int HS; // the horizontal speed (in m/s), can be negative. 29 | int VS; // the vertical speed (in m/s), can be negative. 30 | int F; // the quantity of remaining fuel in liters. 31 | int R; // the rotation angle in degrees (-90 to 90). 32 | int P; // the thrust power (0 to 4). 33 | cin >> X >> Y >> HS >> VS >> F >> R >> P; cin.ignore(); 34 | 35 | // Write an action using cout. DON'T FORGET THE "<< endl" 36 | // To debug: cerr << "Debug messages..." << endl; 37 | 38 | if (VS < -39) 39 | cout << 0 << " " << 4 << endl; 40 | /*else if (VS < -24) 41 | cout << 0 << " " << 3 << endl; 42 | else if (VS < -18) 43 | cout << 0 << " " << 2 << endl; 44 | else if (VS < -12) 45 | cout << 0 << " " << 1 << endl;*/ 46 | else 47 | cout << 0 << " " << 0 << endl; 48 | 49 | //cout << "-20 3" << endl; // R P. R is the desired rotation angle. P is the desired thrust power. 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SingePlayer/Easy/The Travelling Salesman Problem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Point 9 | { 10 | public int x; 11 | public int y; 12 | public Point(int X, int Y) 13 | { 14 | x = X; 15 | y = Y; 16 | } 17 | } 18 | 19 | class Solution 20 | { 21 | static double Distance(Point P1, Point P2) 22 | { 23 | return Math.Sqrt(Math.Pow(P1.x-P2.x, 2) + Math.Pow(P1.y-P2.y, 2)); 24 | } 25 | 26 | static void Main(string[] args) 27 | { 28 | var Points = new List(); 29 | int N = int.Parse(Console.ReadLine()); 30 | for (int i = 0; i < N; i++) 31 | { 32 | string[] inputs = Console.ReadLine().Split(' '); 33 | int X = int.Parse(inputs[0]); 34 | int Y = int.Parse(inputs[1]); 35 | Points.Add(new Point(X, Y)); 36 | } 37 | 38 | var FirstPoint = Points[0]; 39 | var LastPoint = FirstPoint; 40 | Points.RemoveAt(0); 41 | 42 | double TotalDist = 0; 43 | while (Points.Count > 0) 44 | { 45 | double MinDist = int.MaxValue; 46 | Point ClosestPoint = null; 47 | foreach (var P in Points) 48 | { 49 | double Dist = Distance(LastPoint, P); 50 | if (Dist < MinDist) 51 | { 52 | MinDist = Dist; 53 | ClosestPoint = P; 54 | } 55 | } 56 | Console.Error.WriteLine(MinDist); 57 | TotalDist += MinDist; 58 | LastPoint = ClosestPoint; 59 | Points.Remove(ClosestPoint); 60 | } 61 | 62 | TotalDist += Distance(LastPoint, FirstPoint); 63 | Console.WriteLine(Math.Round(TotalDist)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SingePlayer/Medium/There is no Spoon - Episode 1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | int width; // the number of cells on the X axis 11 | cin >> width; cin.ignore(); 12 | int height; // the number of cells on the Y axis 13 | cin >> height; cin.ignore(); 14 | 15 | vector> grid(height, vector(width, false)); 16 | 17 | for (int i = 0; i < height; i++) { 18 | string line; // width characters, each either 0 or . 19 | getline(cin, line); 20 | 21 | for (unsigned int j = 0; j < line.size(); ++j) { 22 | if (line[j] == '0') { 23 | grid[i][j] = true; 24 | } 25 | } 26 | } 27 | 28 | for (unsigned int h = 0; h < height; ++h) { 29 | for (unsigned int w = 0; w < width; ++w) { 30 | if (grid[h][w]) { 31 | cout << w << " " << h << " "; 32 | bool found = false; 33 | for (unsigned int i = w+1; i < width; ++i) { 34 | if (grid[h][i]) { 35 | cout << i << " " << h << " "; 36 | found = true; 37 | break; 38 | } 39 | } 40 | if (!found) { 41 | cout << "-1 -1 "; 42 | } 43 | 44 | found = false; 45 | for (unsigned int j = h+1; j < height; ++j) { 46 | if (grid[j][w]) { 47 | cout << w << " " << j << endl; 48 | found = true; 49 | break; 50 | } 51 | } 52 | if (!found) { 53 | cout << "-1 -1" << endl; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Community Puzzles/Simple fraction to mixed number.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int N; 9 | scanf("%d", &N); 10 | for (int i = 0; i < N; i++) { 11 | char xY[16]; 12 | scanf("%s", xY); 13 | 14 | int X = atoi(strtok(xY, "/")); 15 | int Y = atoi(strtok(NULL, "/")); 16 | 17 | int negative = 0; 18 | if (X < 0) { 19 | X = -X; 20 | negative ^= 1; 21 | } 22 | if (Y < 0) { 23 | Y = -Y; 24 | negative ^= 1; 25 | } 26 | 27 | if (Y == 0) { 28 | printf("DIVISION BY ZERO"); 29 | } 30 | else if (X == 0) { 31 | printf("0"); 32 | } 33 | else { 34 | if (negative) 35 | printf("-"); 36 | 37 | int integer = X / Y; 38 | if (integer != 0) { 39 | printf("%d", integer); 40 | 41 | if (X % Y) 42 | printf(" "); 43 | } 44 | 45 | if (X % Y) { 46 | X -= integer * Y; 47 | 48 | int divisorFound = 1; 49 | while (divisorFound) { 50 | divisorFound = 0; 51 | int maxDivisor = fmin(X, Y); 52 | for (int j = maxDivisor; j > 1; j--) { 53 | if ((X % j == 0) && (Y % j == 0)) { 54 | X /= j; 55 | Y /= j; 56 | divisorFound = 1; 57 | break; 58 | } 59 | } 60 | } 61 | 62 | printf("%d/%d", X, Y); 63 | } 64 | } 65 | printf("\n"); 66 | } 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /Community Puzzles/Laser and mirrors.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import math 3 | 4 | u, v = [int(i) for i in input().split()] 5 | 6 | pos = (0,u) 7 | dir = (1,-1) 8 | 9 | length = 0 10 | 11 | while True: 12 | if dir == (1,-1): 13 | if v - pos[0] < pos[1]: 14 | dist = v - pos[0] 15 | pos = (pos[0] + dist, pos[1] - dist) 16 | dir = (-1,-1) 17 | elif v - pos[0] > pos[1]: 18 | dist = pos[1] 19 | pos = (pos[0] + dist, pos[1] - dist) 20 | dir = (1,1) 21 | else: 22 | length += pos[1] 23 | print('B ' + str(length)) 24 | break 25 | elif dir == (-1,-1): 26 | if pos[0] < pos[1]: 27 | dist = pos[0] 28 | pos = (pos[0] - dist, pos[1] - dist) 29 | dir = (1,-1) 30 | elif pos[0] > pos[1]: 31 | dist = pos[1] 32 | pos = (pos[0] - dist, pos[1] - dist) 33 | dir = (-1,1) 34 | else: 35 | length += pos[1] 36 | print('A ' + str(length)) 37 | break 38 | elif dir == (1,1): 39 | if v - pos[0] < u - pos[1]: 40 | dist = v - pos[0] 41 | pos = (pos[0] + dist, pos[1] + dist) 42 | dir = (-1,1) 43 | elif v - pos[0] > u - pos[1]: 44 | dist = u - pos[1] 45 | pos = (pos[0] + dist, pos[1] + dist) 46 | dir = (1,-1) 47 | else: 48 | length += u - pos[1] 49 | print('C ' + str(length)) 50 | break 51 | elif dir == (-1,1): 52 | if pos[0] < u - pos[1]: 53 | dist = pos[0] 54 | pos = (pos[0] - dist, pos[1] + dist) 55 | dir = (1,1) 56 | elif pos[0] > u - pos[1]: 57 | dist = u - pos[1] 58 | pos = (pos[0] - dist, pos[1] + dist) 59 | dir = (-1,-1) 60 | else: 61 | length += pos[0] 62 | print('S ' + str(length)) 63 | break 64 | 65 | length += dist 66 | -------------------------------------------------------------------------------- /Community Puzzles/Bruce Lee.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static void Main(string[] args) 11 | { 12 | string ENCRYPT = Console.ReadLine(); 13 | var parts = ENCRYPT.Split(); 14 | 15 | // Convert unary to binary 16 | string binary = ""; 17 | int type = -1; 18 | for (int i = 0; i < parts.Length; ++i) 19 | { 20 | if (type == -1) 21 | { 22 | if (parts[i].Length == 1) 23 | type = 1; 24 | else if (parts[i].Length == 2) 25 | type = 0; 26 | else 27 | { 28 | Console.WriteLine("INVALID"); 29 | return; 30 | } 31 | } 32 | else if (type == 0) 33 | { 34 | for (int j = 0; j < parts[i].Length; ++j) 35 | binary += "0"; 36 | 37 | type = -1; 38 | } 39 | else if (type == 1) 40 | { 41 | for (int j = 0; j < parts[i].Length; ++j) 42 | binary += "1"; 43 | 44 | type = -1; 45 | } 46 | } 47 | 48 | // Binary string has to contain 7 bits per character 49 | if (binary.Length % 7 != 0) 50 | { 51 | Console.WriteLine("INVALID"); 52 | return; 53 | } 54 | 55 | // Extract characters from binary string 56 | for (int i = 0; i < binary.Length / 7; ++i) 57 | { 58 | string charBinary = binary.Substring(7*i, 7); 59 | 60 | int charToDisplay = 0; 61 | for (int j = 0; j < 7; ++j) 62 | charToDisplay += (int)(Math.Pow(2, 6-j) * (charBinary[j] - '0')); 63 | 64 | Console.Write((char)charToDisplay); 65 | } 66 | 67 | Console.Write("\n"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Power of Thor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | int LX; // the X position of the light of power 15 | int LY; // the Y position of the light of power 16 | int TX; // Thor's starting X position 17 | int TY; // Thor's starting Y position 18 | cin >> LX >> LY >> TX >> TY; cin.ignore(); 19 | 20 | // game loop 21 | while (1) { 22 | int E; // The level of Thor's remaining energy, representing the number of moves he can still make. 23 | cin >> E; cin.ignore(); 24 | 25 | if (LX > TX) 26 | { 27 | if (LY > TY) 28 | { 29 | TX += 1; 30 | TY += 1; 31 | cout << "SE" << endl; 32 | } 33 | else if (LY < TY) 34 | { 35 | TX += 1; 36 | TY -= 1; 37 | cout << "NE" << endl; 38 | } 39 | else 40 | { 41 | TX += 1; 42 | cout << "E" << endl; 43 | } 44 | } 45 | else if (LX < TX) 46 | { 47 | if (LY > TY) 48 | { 49 | TX -= 1; 50 | TY += 1; 51 | cout << "SW" << endl; 52 | } 53 | else if (LY < TY) 54 | { 55 | TX -= 1; 56 | TY -= 1; 57 | cout << "NW" << endl; 58 | } 59 | else 60 | { 61 | TX -= 1; 62 | cout << "W" << endl; 63 | } 64 | } 65 | else 66 | { 67 | if (LY > TY) 68 | { 69 | TY += 1; 70 | cout << "S" << endl; 71 | } 72 | else if (LY < TY) 73 | { 74 | TY -= 1; 75 | cout << "N" << endl; 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /SingePlayer/Medium/The Gift.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | int totalBudget = 0; 15 | vector budget; 16 | 17 | int N; 18 | cin >> N; cin.ignore(); 19 | int C; 20 | cin >> C; cin.ignore(); 21 | for (int i = 0; i < N; i++) { 22 | int B; 23 | cin >> B; cin.ignore(); 24 | 25 | budget.push_back(B); 26 | totalBudget += B; 27 | } 28 | 29 | sort(budget.begin(), budget.end()); 30 | 31 | if (C > totalBudget) 32 | cout << "IMPOSSIBLE" << endl; 33 | else 34 | { 35 | int remainingOods = N; 36 | int remainingCost = C; 37 | 38 | while (remainingOods > 0) 39 | { 40 | bool averagePossible = true; 41 | int average = remainingCost / remainingOods; 42 | int remainder = remainingCost % remainingOods; 43 | for (int i = N - remainingOods; i < N; ++i) 44 | { 45 | if (budget[i] <= average) 46 | { 47 | cout << budget[i] << endl; 48 | remainingCost -= budget[i]; 49 | remainingOods--; 50 | averagePossible = false; 51 | } 52 | else 53 | { 54 | if (averagePossible) 55 | { 56 | for (int j = i; j < N - remainder; ++j) 57 | cout << average << endl; 58 | 59 | for (int j = N - remainder; j < N; ++j) 60 | cout << average+1 << endl; 61 | 62 | remainingOods = 0; 63 | break; 64 | } 65 | else // A new average should be calculated 66 | break; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Bender - The Money Machine.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | int N; 13 | unsigned int search(map>>& grid) 14 | { 15 | vector money(N, 0); 16 | auto fringe = queue>{}; 17 | fringe.push({0, 0}); 18 | 19 | while (!fringe.empty()) 20 | { 21 | pair roomNr = fringe.front(); 22 | fringe.pop(); 23 | 24 | if (money[roomNr.second] < money[roomNr.first] + grid[roomNr.second].first) 25 | { 26 | money[roomNr.second] = money[roomNr.first] + grid[roomNr.second].first; 27 | 28 | for (auto& room : grid[roomNr.second].second) 29 | { 30 | if (room != -1) 31 | fringe.push({roomNr.second, room}); 32 | } 33 | } 34 | } 35 | 36 | return *max_element(money.begin(), money.end()); 37 | } 38 | 39 | int main() 40 | { 41 | map>> grid; 42 | set exits; 43 | 44 | cin >> N; cin.ignore(); 45 | for (int i = 0; i < N; i++) { 46 | string room; 47 | getline(cin, room); 48 | 49 | string roomNr; 50 | string money; 51 | string exit1; 52 | string exit2; 53 | stringstream ss(room); 54 | ss >> roomNr; 55 | ss >> money; 56 | ss >> exit1; 57 | ss >> exit2; 58 | 59 | grid[stoi(roomNr)].first = stoi(money); 60 | 61 | if (exit1 != "E") 62 | grid[stoi(roomNr)].second.push_back(stoi(exit1)); 63 | else 64 | { 65 | grid[stoi(roomNr)].second.push_back(-1); 66 | exits.insert(stoi(roomNr)); 67 | } 68 | 69 | if (exit2 != "E") 70 | grid[stoi(roomNr)].second.push_back(stoi(exit2)); 71 | else 72 | { 73 | grid[stoi(roomNr)].second.push_back(-1); 74 | exits.insert(stoi(roomNr)); 75 | } 76 | } 77 | 78 | cout << search(grid) << endl; 79 | } 80 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Genome Sequencing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int main() 10 | { 11 | int N; 12 | cin >> N; cin.ignore(); 13 | 14 | vector subseqs(N); 15 | vector order(N); 16 | 17 | for (int i = 0; i < N; i++) { 18 | string subseq; 19 | cin >> subseq; cin.ignore(); 20 | 21 | subseqs[i] = subseq; 22 | order[i] = i; 23 | } 24 | 25 | string bestWord; 26 | string lastWord; 27 | do 28 | { 29 | bool match = false; 30 | string lastWord = subseqs[order[0]]; 31 | for (unsigned int i = 1; i < subseqs.size(); ++i) 32 | { 33 | match = false; 34 | string first = lastWord; 35 | string second = subseqs[order[i]]; 36 | 37 | for (unsigned int j = 0; j < first.size(); ++j) 38 | { 39 | if (second.size() >= first.size() - j) 40 | { 41 | match = equal(first.begin() + j, 42 | first.end(), 43 | second.begin()); 44 | 45 | if (match) 46 | { 47 | lastWord = first + second.substr(first.size() - j); 48 | break; 49 | } 50 | } 51 | else 52 | { 53 | match = equal(first.begin() + j, 54 | first.begin() + j + second.size(), 55 | second.begin()); 56 | 57 | if (match) 58 | { 59 | lastWord = first; 60 | break; 61 | } 62 | } 63 | } 64 | 65 | // If no overlap, place the sequences begind each other 66 | if (!match) 67 | lastWord = first + second; 68 | } 69 | 70 | if (bestWord.empty() || (lastWord.size() < bestWord.size())) 71 | bestWord = lastWord; 72 | } 73 | while (next_permutation(order.begin(), order.end())); 74 | 75 | cout << bestWord.size() << endl; 76 | } 77 | -------------------------------------------------------------------------------- /Community Puzzles/ASCII ART : Glass Stacking.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void drawFirstRow(int count, int spaces) 6 | { 7 | for (int i = 0; i < spaces; ++i) { 8 | printf(" "); 9 | } 10 | 11 | for (int i = 0; i < count-1; ++i) { 12 | printf(" *** "); 13 | printf(" "); 14 | } 15 | printf(" *** "); 16 | 17 | for (int i = 0; i < spaces; ++i) { 18 | printf(" "); 19 | } 20 | 21 | printf("\n"); 22 | } 23 | 24 | void drawMiddleRow(int count, int spaces) 25 | { 26 | for (int i = 0; i < spaces; ++i) { 27 | printf(" "); 28 | } 29 | 30 | for (int i = 0; i < count-1; ++i) { 31 | printf(" * * "); 32 | printf(" "); 33 | } 34 | printf(" * * "); 35 | 36 | for (int i = 0; i < spaces; ++i) { 37 | printf(" "); 38 | } 39 | 40 | printf("\n"); 41 | } 42 | 43 | void drawLastRow(int count, int spaces) 44 | { 45 | for (int i = 0; i < spaces; ++i) { 46 | printf(" "); 47 | } 48 | 49 | for (int i = 0; i < count-1; ++i) { 50 | printf("*****"); 51 | printf(" "); 52 | } 53 | printf("*****"); 54 | 55 | for (int i = 0; i < spaces; ++i) { 56 | printf(" "); 57 | } 58 | 59 | printf("\n"); 60 | } 61 | 62 | void drawGlasses(int count, int glassesInBottomRow) 63 | { 64 | int width = glassesInBottomRow*5 + (glassesInBottomRow-1); 65 | int spaces = (width - (count*5 + (count-1))) / 2; 66 | 67 | drawFirstRow(count, spaces); 68 | drawMiddleRow(count, spaces); 69 | drawMiddleRow(count, spaces); 70 | drawLastRow(count, spaces); 71 | } 72 | 73 | int main() 74 | { 75 | int N; 76 | scanf("%d", &N); 77 | 78 | int glassesUsed = 0; 79 | int glassesInBottomRow = 0; 80 | for (int i = 1; i < N; ++i) { 81 | glassesUsed += i; 82 | if (glassesUsed > N) { 83 | glassesUsed -= i; 84 | glassesInBottomRow = i-1; 85 | break; 86 | } 87 | } 88 | 89 | if (glassesInBottomRow == 0) { 90 | glassesUsed = 1; 91 | glassesInBottomRow = 1; 92 | } 93 | 94 | for (int i = 1; i <= glassesInBottomRow; ++i) { 95 | drawGlasses(i, glassesInBottomRow); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Community Puzzles/The greatest number.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static void Main(string[] args) 11 | { 12 | int N = int.Parse(Console.ReadLine()); 13 | string input = Console.ReadLine(); 14 | 15 | var chars = input.Split(); 16 | Array.Sort(chars); 17 | 18 | // Exception for when all numbers are 0 19 | if (chars[chars.Length-1] == "0") 20 | { 21 | Console.WriteLine(0); 22 | return; 23 | } 24 | 25 | if (chars[0] == "-") 26 | { 27 | Console.Write('-'); 28 | 29 | if (chars[1] == ".") 30 | { 31 | Console.Write(chars[2]); 32 | Console.Write("."); 33 | 34 | for (int i = 3; i < chars.Length; ++i) 35 | Console.Write(chars[i]); 36 | } 37 | else // No comma 38 | { 39 | var index = 1; 40 | while (chars[index] == "0") 41 | index++; 42 | 43 | for (int i = index; i < chars.Length; ++i) 44 | Console.Write(chars[i]); 45 | } 46 | } 47 | else // Number is positive 48 | { 49 | if (chars[0] == ".") 50 | { 51 | Console.Write(chars[chars.Length-1]); 52 | 53 | for (int i = chars.Length-2; i > 1; --i) 54 | Console.Write(chars[i]); 55 | 56 | // A zero behind the comma is dropped 57 | if (chars[1] != "0") 58 | { 59 | Console.Write('.'); 60 | Console.Write(chars[1]); 61 | } 62 | } 63 | else // No comma 64 | { 65 | var index = 1; 66 | while (chars[index] == "0") 67 | index++; 68 | 69 | for (int i = chars.Length; i > 0; --i) 70 | Console.Write(chars[i-1]); 71 | } 72 | } 73 | 74 | Console.Write("\n"); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Roller Coaster.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | int L; 11 | int C; 12 | int N; 13 | cin >> L >> C >> N; cin.ignore(); 14 | 15 | vector queue(N); 16 | 17 | for (int i = 0; i < N; i++) { 18 | int Pi; 19 | cin >> Pi; cin.ignore(); 20 | 21 | queue[i] = Pi; 22 | } 23 | 24 | long long earnings = 0; 25 | if (C < N) 26 | { 27 | int index = 0; 28 | for (int c = 0; c < C; ++c) 29 | { 30 | int beginIndex = index; 31 | int remainingSpace = L; 32 | while (queue[index] <= remainingSpace) 33 | { 34 | remainingSpace -= queue[index]; 35 | 36 | if (index < queue.size()-1) 37 | ++index; 38 | else 39 | index = 0; 40 | 41 | // Don't let the same people board twice 42 | if (index == beginIndex) 43 | break; 44 | } 45 | 46 | earnings += L - remainingSpace; 47 | } 48 | } 49 | else // Less groups than rides 50 | { 51 | // Calculate the earning for each group standing in the front 52 | vector> earningsQueue(N); 53 | for (int i = 0; i < N; ++i) 54 | { 55 | int index = i; 56 | int beginIndex = index; 57 | int remainingSpace = L; 58 | while (queue[index] <= remainingSpace) 59 | { 60 | remainingSpace -= queue[index]; 61 | 62 | if (index < queue.size()-1) 63 | ++index; 64 | else 65 | index = 0; 66 | 67 | // Don't let the same people board twice 68 | if (index == beginIndex) 69 | break; 70 | } 71 | 72 | earningsQueue[i] = {L - remainingSpace, index}; 73 | } 74 | 75 | // Run the algorithm on the cached values 76 | int index = 0; 77 | for (int c = 0; c < C; ++c) 78 | { 79 | earnings += earningsQueue[index].first; 80 | index = earningsQueue[index].second; 81 | } 82 | } 83 | 84 | cout << earnings << endl; 85 | } 86 | -------------------------------------------------------------------------------- /SingePlayer/Hard/CGX Formatter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int spaces = 0; 10 | bool newLine = true; 11 | 12 | void printSpaces(int spaces) 13 | { 14 | for (int i = 0; i < spaces; ++i) 15 | cout << ' '; 16 | } 17 | 18 | void printNewLine() 19 | { 20 | cout << endl; 21 | newLine = true; 22 | } 23 | 24 | void print(char c) 25 | { 26 | if (newLine) 27 | { 28 | printSpaces(spaces); 29 | newLine = false; 30 | } 31 | 32 | cout << c; 33 | } 34 | 35 | int main() 36 | { 37 | 38 | int N; 39 | cin >> N; cin.ignore(); 40 | for (int i = 0; i < N; i++) { 41 | string CGXLine; 42 | getline(cin, CGXLine); 43 | 44 | bool readingString = false; 45 | for (char c : CGXLine) 46 | { 47 | if (readingString) 48 | { 49 | print(c); 50 | 51 | if (c == '\'') 52 | readingString = false; 53 | } 54 | else 55 | { 56 | switch (c) 57 | { 58 | case ' ': 59 | case '\t': 60 | break; 61 | 62 | case '(': 63 | if (!newLine) 64 | printNewLine(); 65 | print('('); 66 | printNewLine(); 67 | spaces += 4; 68 | break; 69 | 70 | case ')': 71 | spaces -= 4; 72 | if (!newLine) 73 | printNewLine(); 74 | print(')'); 75 | break; 76 | 77 | case '\'': 78 | readingString = !readingString; 79 | print('\''); 80 | break; 81 | 82 | case ';': 83 | print(';'); 84 | printNewLine(); 85 | break; 86 | 87 | default: 88 | print(c); 89 | break; 90 | }; 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Community Puzzles/CGFunge interpreter.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | x = 0 4 | y = 0 5 | direction = (1,0) 6 | stringMode = False 7 | skipChar = False 8 | grid = [] 9 | stack = [] 10 | 11 | n = int(input()) 12 | for i in range(n): 13 | line = input() 14 | grid.append([]) 15 | for c in line: 16 | grid[-1].append(c) 17 | 18 | # All lines must have equal length 19 | maxLineLen = len(max(grid, key=len)) 20 | for row in grid: 21 | for k in range(maxLineLen - len(row)): 22 | row.append(' ') 23 | 24 | cell = grid[y][x] 25 | while True: 26 | if skipChar: 27 | skipChar = False 28 | elif stringMode: 29 | if cell != '"': 30 | stack.append(ord(cell)) 31 | else: 32 | stringMode = False 33 | elif cell >= '0' and cell <= '9': 34 | stack.append(int(cell)) 35 | elif cell == '+': 36 | val1 = stack.pop() 37 | val2 = stack.pop() 38 | stack.append((val1 + val2) % 256) 39 | elif cell == '-': 40 | val1 = stack.pop() 41 | val2 = stack.pop() 42 | stack.append((val2 - val1) % 256) 43 | elif cell == '*': 44 | val1 = stack.pop() 45 | val2 = stack.pop() 46 | stack.append((val1 * val2) % 256) 47 | elif cell == '>': 48 | direction = (1,0) 49 | elif cell == '<': 50 | direction = (-1,0) 51 | elif cell == 'v': 52 | direction = (0,1) 53 | elif cell == '^': 54 | direction = (0,-1) 55 | elif cell == 'S': 56 | skipChar = True 57 | elif cell == '"': 58 | stringMode = True 59 | elif cell == 'I': 60 | print(stack.pop(), end='') 61 | elif cell == 'C': 62 | print(chr(stack.pop()), end='') 63 | elif cell == 'P': 64 | stack.pop() 65 | elif cell == 'X': 66 | val1 = stack.pop() 67 | val2 = stack.pop() 68 | stack.append(val1) 69 | stack.append(val2) 70 | elif cell == 'D': 71 | val = stack.pop() 72 | stack.append(val) 73 | stack.append(val) 74 | elif cell == '_': 75 | if stack.pop() == 0: 76 | direction = (1,0) 77 | else: 78 | direction = (-1,0) 79 | elif cell == '|': 80 | if stack.pop() == 0: 81 | direction = (0,1) 82 | else: 83 | direction = (0,-1) 84 | elif cell == 'E': 85 | break 86 | 87 | x += direction[0] 88 | y += direction[1] 89 | cell = grid[y][x] 90 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Scrabble.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int charVal(char c) 10 | { 11 | switch (c) 12 | { 13 | case 'e': 14 | case 'a': 15 | case 'i': 16 | case 'o': 17 | case 'n': 18 | case 'r': 19 | case 't': 20 | case 'l': 21 | case 's': 22 | case 'u': 23 | return 1; 24 | 25 | case 'd': 26 | case 'g': 27 | return 2; 28 | 29 | case 'b': 30 | case 'c': 31 | case 'm': 32 | case 'p': 33 | return 3; 34 | 35 | case 'f': 36 | case 'h': 37 | case 'v': 38 | case 'w': 39 | case 'y': 40 | return 4; 41 | 42 | case 'k': 43 | return 5; 44 | 45 | case 'j': 46 | case 'x': 47 | return 8; 48 | 49 | case 'q': 50 | case 'z': 51 | return 10; 52 | }; 53 | } 54 | 55 | int main() 56 | { 57 | vector words; 58 | 59 | int N; 60 | cin >> N; cin.ignore(); 61 | for (int i = 0; i < N; i++) { 62 | string W; 63 | getline(cin, W); 64 | 65 | if (W.length() <= 7) 66 | words.push_back(W); 67 | } 68 | string LETTERS; 69 | getline(cin, LETTERS); 70 | 71 | // Find all possible words that can be made with the 7 letters 72 | vector possibleWords; 73 | for (const string& word : words) 74 | { 75 | string sortedWord = word; 76 | sort(LETTERS.begin(), LETTERS.end()); 77 | sort(sortedWord.begin(), sortedWord.end()); 78 | if (includes(LETTERS.begin(), LETTERS.end(), sortedWord.begin(), sortedWord.end())) 79 | possibleWords.push_back(word); 80 | } 81 | 82 | // Find the word that gives us the most letters 83 | int maxVal = 0; 84 | string bestWord; 85 | for (const string& word : possibleWords) 86 | { 87 | int val = 0; 88 | for (char c : word) 89 | val += charVal(c); 90 | 91 | if (val > maxVal) 92 | { 93 | maxVal = val; 94 | bestWord = word; 95 | } 96 | } 97 | 98 | cout << bestWord << endl; 99 | } 100 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Mayan Calculation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | /** 10 | * Auto-generated code below aims at helping you parse 11 | * the standard input according to the problem statement. 12 | **/ 13 | int main() 14 | { 15 | vector numbers(20); 16 | string num1, num2; 17 | 18 | int L; 19 | int H; 20 | cin >> L >> H; cin.ignore(); 21 | for (int i = 0; i < H; i++) { 22 | string numeral; 23 | cin >> numeral; cin.ignore(); 24 | 25 | for (int j = 0; j < 20; ++j) 26 | numbers[j].append(numeral.substr(j*L, L)); 27 | } 28 | int S1; 29 | cin >> S1; cin.ignore(); 30 | for (int i = 0; i < S1; i++) { 31 | string num1Line; 32 | cin >> num1Line; cin.ignore(); 33 | num1.append(num1Line); 34 | } 35 | int S2; 36 | cin >> S2; cin.ignore(); 37 | for (int i = 0; i < S2; i++) { 38 | string num2Line; 39 | cin >> num2Line; cin.ignore(); 40 | num2.append(num2Line); 41 | } 42 | 43 | string operation; 44 | cin >> operation; cin.ignore(); 45 | 46 | long long num1Value = 0; 47 | for (int j = 0; j < num1.size() / (H*L); ++j) 48 | { 49 | for (int i = 0; i < numbers.size(); ++i) 50 | { 51 | if (numbers[i] == num1.substr(j*H*L, H*L)) 52 | num1Value += i * pow(20, (num1.size() / (H*L)) - j - 1); 53 | } 54 | } 55 | 56 | long long num2Value = 0; 57 | for (int j = 0; j < num2.size() / (H*L); ++j) 58 | { 59 | for (int i = 0; i < numbers.size(); ++i) 60 | { 61 | if (numbers[i] == num2.substr(j*H*L, H*L)) 62 | num2Value += i * pow(20, (num2.size() / (H*L)) - j - 1); 63 | } 64 | } 65 | 66 | long long result; 67 | if (operation == "+") 68 | result = num1Value + num2Value; 69 | else if (operation == "-") 70 | result = num1Value - num2Value; 71 | if (operation == "*") 72 | result = num1Value * num2Value; 73 | if (operation == "/") 74 | result = num1Value / num2Value; 75 | 76 | deque resultingNumbers = {result}; 77 | while (result > 20) 78 | { 79 | resultingNumbers.pop_front(); 80 | resultingNumbers.push_front(result % 20); 81 | resultingNumbers.push_front(result / 20); 82 | result /= 20; 83 | } 84 | 85 | for (long long num : resultingNumbers) 86 | { 87 | for (int i = 0; i < H; ++i) 88 | cout << numbers[num].substr(i*L, L) << endl; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Indiana - Level 1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | /** 11 | * Auto-generated code below aims at helping you parse 12 | * the standard input according to the problem statement. 13 | **/ 14 | int main() 15 | { 16 | map, int> grid; 17 | 18 | int W; // number of columns. 19 | int H; // number of rows. 20 | cin >> W >> H; cin.ignore(); 21 | for (int i = 0; i < H; i++) { 22 | string LINE; // represents a line in the grid and contains W integers. Each integer represents one room of a given type. 23 | getline(cin, LINE); 24 | 25 | stringstream ss(LINE); 26 | for (int j = 0; j < W; ++j) 27 | { 28 | string temp; 29 | ss >> temp; 30 | grid[{j, i}] = stoi(temp); 31 | } 32 | } 33 | int EX; // the coordinate along the X axis of the exit (not useful for this first mission, but must be read). 34 | cin >> EX; cin.ignore(); 35 | 36 | // game loop 37 | while (1) { 38 | int XI; 39 | int YI; 40 | string POS; 41 | cin >> XI >> YI >> POS; cin.ignore(); 42 | 43 | switch(grid[{XI, YI}]) 44 | { 45 | case 1: 46 | case 3: 47 | case 7: 48 | case 8: 49 | case 9: 50 | case 12: 51 | case 13: 52 | cout << XI << " " << (YI+1) << endl; 53 | break; 54 | 55 | case 2: 56 | case 6: 57 | { 58 | if (POS == "LEFT") 59 | cout << (XI+1) << " " << YI << endl; 60 | else if (POS == "RIGHT") 61 | cout << (XI-1) << " " << YI << endl; 62 | break; 63 | } 64 | 65 | case 4: 66 | { 67 | if (POS == "TOP") 68 | cout << (XI-1) << " " << YI << endl; 69 | else if (POS == "RIGHT") 70 | cout << XI << " " << (YI+1) << endl; 71 | break; 72 | } 73 | 74 | case 5: 75 | { 76 | if (POS == "TOP") 77 | cout << (XI+1) << " " << YI << endl; 78 | else if (POS == "LEFT") 79 | cout << XI << " " << (YI+1) << endl; 80 | break; 81 | } 82 | 83 | case 10: 84 | cout << (XI-1) << " " << YI << endl; 85 | break; 86 | 87 | case 11: 88 | cout << (XI+1) << " " << YI << endl; 89 | break; 90 | 91 | default: 92 | cerr << "Unknown type" << endl; 93 | }; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Community Puzzles/Maze.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static void Main(string[] args) 11 | { 12 | string[] inputs; 13 | inputs = Console.ReadLine().Split(' '); 14 | int W = int.Parse(inputs[0]); 15 | int H = int.Parse(inputs[1]); 16 | inputs = Console.ReadLine().Split(' '); 17 | int X = int.Parse(inputs[0]); 18 | int Y = int.Parse(inputs[1]); 19 | 20 | int[,] grid = new int[W,H]; 21 | for (int i = 0; i < H; i++) 22 | { 23 | string R = Console.ReadLine(); 24 | for (int j = 0; j < W; j++) 25 | grid[j,i] = R[j]; 26 | } 27 | 28 | var positions = new List>(); 29 | positions.Add(new Tuple(X,Y)); 30 | 31 | var answers = new List>(); 32 | while (positions.Count > 0) 33 | { 34 | var newPositions = new List>(); 35 | foreach (var pos in positions) 36 | { 37 | // A position can be added twice when two of its neighbors were inspected at the same time 38 | if (grid[pos.Item1, pos.Item2] == '+') 39 | continue; 40 | 41 | grid[pos.Item1, pos.Item2] = '+'; 42 | 43 | if (pos.Item2 + 1 < H && grid[pos.Item1, pos.Item2 + 1] == '.') 44 | newPositions.Add(new Tuple(pos.Item1, pos.Item2 + 1)); 45 | if (pos.Item2 > 0 && grid[pos.Item1, pos.Item2 - 1] == '.') 46 | newPositions.Add(new Tuple(pos.Item1, pos.Item2 - 1)); 47 | if (pos.Item1 + 1 < W && grid[pos.Item1 + 1, pos.Item2] == '.') 48 | newPositions.Add(new Tuple(pos.Item1 + 1, pos.Item2)); 49 | if (pos.Item1 > 0 && grid[pos.Item1 - 1, pos.Item2] == '.') 50 | newPositions.Add(new Tuple(pos.Item1 - 1, pos.Item2)); 51 | 52 | if (pos.Item1 == 0 || pos.Item2 == 0 || pos.Item1 == W-1 || pos.Item2 == H-1) 53 | answers.Add(new Tuple(pos.Item1, pos.Item2)); 54 | } 55 | 56 | positions = newPositions; 57 | } 58 | 59 | answers.Sort((x, y) => { 60 | int result = x.Item1.CompareTo(y.Item1); 61 | return result == 0 ? x.Item2.CompareTo(y.Item2) : result; 62 | }); 63 | 64 | Console.WriteLine(answers.Count); 65 | foreach (var pos in answers) 66 | Console.WriteLine(pos.Item1.ToString() + " " + pos.Item2.ToString()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Defibrillators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | /** 11 | * Auto-generated code below aims at helping you parse 12 | * the standard input according to the problem statement. 13 | **/ 14 | int main() 15 | { 16 | string LON; 17 | cin >> LON; cin.ignore(); 18 | string LAT; 19 | cin >> LAT; cin.ignore(); 20 | int N; 21 | cin >> N; cin.ignore(); 22 | 23 | auto COMMA_POS_LON = LON.find(","); 24 | assert(COMMA_POS_LON != string::npos); 25 | 26 | auto COMMA_POS_LAT = LAT.find(","); 27 | assert(COMMA_POS_LAT != string::npos); 28 | 29 | LON.replace(COMMA_POS_LON, 1, 1, '.'); 30 | LAT.replace(COMMA_POS_LAT, 1, 1, '.'); 31 | 32 | double longitudeA = stod(LON) / 180.0 * M_PI; 33 | double latitudeA = stod(LAT) / 180.0 * M_PI; 34 | 35 | double minDist = numeric_limits::infinity(); 36 | string address; 37 | 38 | for (int i = 0; i < N; i++) { 39 | string DEFIB; 40 | getline(cin, DEFIB); 41 | 42 | auto FIRST_SEMICOLON = DEFIB.find(";"); 43 | assert(FIRST_SEMICOLON != string::npos); 44 | 45 | auto SECOND_SEMICOLON = DEFIB.find(";", FIRST_SEMICOLON + 1); 46 | assert(SECOND_SEMICOLON != string::npos); 47 | 48 | auto THIRD_SEMICOLON = DEFIB.find(";", SECOND_SEMICOLON + 1); 49 | assert(THIRD_SEMICOLON != string::npos); 50 | 51 | auto FOURTH_SEMICOLON = DEFIB.find(";", THIRD_SEMICOLON + 1); 52 | assert(FOURTH_SEMICOLON != string::npos); 53 | 54 | auto FIFTH_SEMICOLON = DEFIB.find(";", FOURTH_SEMICOLON + 1); 55 | assert(FIFTH_SEMICOLON != string::npos); 56 | 57 | COMMA_POS_LON = DEFIB.find(",", FOURTH_SEMICOLON + 1); 58 | assert(COMMA_POS_LON != string::npos); 59 | 60 | COMMA_POS_LAT = DEFIB.find(",", FIFTH_SEMICOLON + 1); 61 | assert(COMMA_POS_LAT != string::npos); 62 | 63 | DEFIB.replace(COMMA_POS_LON, 1, 1, '.'); 64 | DEFIB.replace(COMMA_POS_LAT, 1, 1, '.'); 65 | 66 | double longitudeB = stod(DEFIB.substr(FOURTH_SEMICOLON + 1, FIFTH_SEMICOLON - FOURTH_SEMICOLON - 1)) / 180.0 * M_PI; 67 | double latitudeB = stod(DEFIB.substr(FIFTH_SEMICOLON + 1)) / 180.0 * M_PI; 68 | 69 | double x = (longitudeB - longitudeA) * cos((latitudeA + latitudeB) / 2.0); 70 | double y = (latitudeB - latitudeA); 71 | double d = sqrt(x*x + y*y) * 6371; 72 | 73 | if (d < minDist) 74 | { 75 | minDist = d; 76 | address = DEFIB.substr(FIRST_SEMICOLON + 1, SECOND_SEMICOLON - FIRST_SEMICOLON - 1); 77 | } 78 | } 79 | 80 | cout << address << endl; 81 | } 82 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Hidden word.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static List Words = new List(); 11 | static List> Grid = new List>(); 12 | static List> GridRemaining = new List>(); 13 | 14 | static void TryMatchSingWord(int x, int y, int dirX, int dirY, string word) 15 | { 16 | for (int i = 0; i < word.Length; ++i) 17 | { 18 | if (y + i*dirX < 0) 19 | return; 20 | if (x + i*dirY < 0) 21 | return; 22 | if (y + i*dirX >= Grid.Count) 23 | return; 24 | if (x + i*dirY >= Grid[0].Count) 25 | return; 26 | 27 | if (Grid[y + i*dirX][x + i*dirY] != word[i]) 28 | return; 29 | } 30 | 31 | for (int i = 0; i < word.Length; ++i) 32 | GridRemaining[y + i*dirX][x + i*dirY] = false; 33 | } 34 | 35 | static void TryMatchWords(int x, int y) 36 | { 37 | foreach (string word in Words) 38 | { 39 | TryMatchSingWord(x, y, 1, 1, word); 40 | TryMatchSingWord(x, y, 1, 0, word); 41 | TryMatchSingWord(x, y, 1, -1, word); 42 | TryMatchSingWord(x, y, 0, 1, word); 43 | TryMatchSingWord(x, y, 0, -1, word); 44 | TryMatchSingWord(x, y, -1, 1, word); 45 | TryMatchSingWord(x, y, -1, 0, word); 46 | TryMatchSingWord(x, y, -1, -1, word); 47 | } 48 | } 49 | 50 | static void Main(string[] args) 51 | { 52 | int n = int.Parse(Console.ReadLine()); 53 | for (int i = 0; i < n; i++) 54 | { 55 | string aword = Console.ReadLine(); 56 | Words.Add(aword); 57 | } 58 | string[] inputs = Console.ReadLine().Split(' '); 59 | int h = int.Parse(inputs[0]); 60 | int w = int.Parse(inputs[1]); 61 | for (int i = 0; i < h; i++) 62 | { 63 | string line = Console.ReadLine(); 64 | Grid.Add(new List()); 65 | GridRemaining.Add(new List()); 66 | foreach (char c in line) 67 | { 68 | Grid[i].Add(c); 69 | GridRemaining[i].Add(true); 70 | } 71 | } 72 | 73 | for (int y = 0; y < h; y++) 74 | { 75 | for (int x = 0; x < w; x++) 76 | TryMatchWords(x, y); 77 | } 78 | 79 | for (int y = 0; y < h; y++) 80 | { 81 | for (int x = 0; x < w; x++) 82 | { 83 | if (GridRemaining[y][x]) 84 | Console.Write(Grid[y][x]); 85 | } 86 | } 87 | Console.WriteLine(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Community Puzzles/Text alignment.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Auto-generated code below aims at helping you parse 7 | * the standard input according to the problem statement. 8 | **/ 9 | int main() 10 | { 11 | char alignment[8]; 12 | fgets(alignment, 8, stdin); 13 | int N; 14 | scanf("%d", &N); fgetc(stdin); 15 | 16 | char lines[N][257]; 17 | 18 | for (int i = 0; i < N; i++) { 19 | char text[257]; 20 | fgets(text, 257, stdin); 21 | strcpy(lines[i], text); 22 | 23 | if (lines[i][strlen(lines[i])-1] == '\n') 24 | lines[i][strlen(lines[i])-1] = 0; 25 | } 26 | 27 | int length = 0; 28 | for (int i = 0; i < N; i++) { 29 | int len = strlen(lines[i]); 30 | if (len > length) 31 | length = len; 32 | } 33 | 34 | if (strcmp("LEFT\n", alignment) == 0) { 35 | for (int i = 0; i < N; i++) { 36 | printf("%s\n", lines[i]); 37 | } 38 | } 39 | else if (strcmp("RIGHT\n", alignment) == 0) { 40 | for (int i = 0; i < N; i++) { 41 | int len = strlen(lines[i]); 42 | for (int j = 0; j < length - len; ++j) { 43 | printf(" "); 44 | } 45 | printf("%s\n", lines[i]); 46 | } 47 | } 48 | else if (strcmp("CENTER\n", alignment) == 0) { 49 | for (int i = 0; i < N; i++) { 50 | int len = strlen(lines[i]); 51 | for (int j = 0; j < (length - len)/2; ++j) { 52 | printf(" "); 53 | } 54 | printf("%s\n", lines[i]); 55 | } 56 | } 57 | else if (strcmp("JUSTIFY", alignment) == 0) { 58 | for (int i = 0; i < N; i++) { 59 | int words = 1; 60 | int len = strlen(lines[i]); 61 | for (int j = 0; j < len; ++j) { 62 | if (lines[i][j] == ' ') 63 | words++; 64 | } 65 | 66 | if (words > 1) { 67 | int spacesRequired = length - len + words-1; 68 | float spaceWidth = spacesRequired / (words-1); 69 | float totalSpace = 0; 70 | int spacesPlaced = 0; 71 | for (int j = 0; j < len; ++j) { 72 | if (lines[i][j] == ' ') { 73 | totalSpace += spaceWidth; 74 | for (int k = spacesPlaced; k < (int)(totalSpace); ++k) { 75 | spacesPlaced++; 76 | printf(" "); 77 | } 78 | } 79 | else { 80 | printf("%c", lines[i][j]); 81 | } 82 | } 83 | printf("\n"); 84 | } 85 | else { 86 | printf("%s\n", lines[i]); 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Skynet: the Virus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct Node 12 | { 13 | int id; 14 | vector connections; 15 | bool exitNode = false; 16 | }; 17 | 18 | vector nodes; 19 | 20 | pair findShortestPath(int nodeId, vector visited) 21 | { 22 | if (nodes[nodeId].exitNode) 23 | return {0, nodeId}; 24 | else 25 | { 26 | pair bestSolution(numeric_limits::max(), nodeId); 27 | for (auto& connection : nodes[nodeId].connections) 28 | { 29 | bool found = false; 30 | for (auto& visitedId : visited) 31 | { 32 | if (connection->id == visitedId) 33 | found = true; 34 | } 35 | 36 | if (!found) 37 | { 38 | visited.push_back(connection->id); 39 | auto result = findShortestPath(connection->id, visited); 40 | if (result.first < bestSolution.first) 41 | { 42 | bestSolution.first = result.first + 1; 43 | bestSolution.second = connection->id; 44 | } 45 | } 46 | } 47 | 48 | return bestSolution; 49 | } 50 | } 51 | 52 | 53 | /** 54 | * Auto-generated code below aims at helping you parse 55 | * the standard input according to the problem statement. 56 | **/ 57 | int main() 58 | { 59 | int N; // the total number of nodes in the level, including the gateways 60 | int L; // the number of links 61 | int E; // the number of exit gateways 62 | cin >> N >> L >> E; cin.ignore(); 63 | 64 | assert(N > 0); 65 | nodes.resize(N); 66 | for (int i = 0; i < N; ++i) 67 | nodes[i].id = i; 68 | 69 | for (int i = 0; i < L; i++) { 70 | int N1; // N1 and N2 defines a link between these nodes 71 | int N2; 72 | cin >> N1 >> N2; cin.ignore(); 73 | 74 | nodes[N1].connections.push_back(&nodes[N2]); 75 | nodes[N2].connections.push_back(&nodes[N1]); 76 | } 77 | for (int i = 0; i < E; i++) { 78 | int EI; // the index of a gateway node 79 | cin >> EI; cin.ignore(); 80 | 81 | nodes[EI].exitNode = true; 82 | } 83 | 84 | // game loop 85 | while (1) { 86 | int SI; // The index of the node on which the Skynet agent is positioned this turn 87 | cin >> SI; cin.ignore(); 88 | 89 | int TI = findShortestPath(SI, {SI}).second; 90 | nodes[SI].connections.erase(std::find(nodes[SI].connections.begin(), nodes[SI].connections.end(), &nodes[TI])); 91 | nodes[TI].connections.erase(std::find(nodes[TI].connections.begin(), nodes[TI].connections.end(), &nodes[SI])); 92 | cout << SI << " " << TI << endl; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /SingePlayer/Easy/Nature of quadrilaterals.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | using System.Text; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | class Solution 9 | { 10 | static double Angle(int xA, int yA, int xB, int yB, int xC, int yC) 11 | { 12 | double result = Math.Atan2(yC - yB, xC - xB) - Math.Atan2(yA - yB, xA - xB) % (2*Math.PI); 13 | if (result < 0) 14 | return result + 2*Math.PI; 15 | else 16 | return result; 17 | } 18 | 19 | static double Length(int xA, int yA, int xB, int yB) 20 | { 21 | return Math.Sqrt((xA-xB)*(xA-xB) + (yA-yB)*(yA-yB)); 22 | } 23 | 24 | static void Main(string[] args) 25 | { 26 | int n = int.Parse(Console.ReadLine()); 27 | for (int i = 0; i < n; i++) 28 | { 29 | string[] inputs = Console.ReadLine().Split(' '); 30 | string A = inputs[0]; 31 | int xA = int.Parse(inputs[1]); 32 | int yA = int.Parse(inputs[2]); 33 | string B = inputs[3]; 34 | int xB = int.Parse(inputs[4]); 35 | int yB = int.Parse(inputs[5]); 36 | string C = inputs[6]; 37 | int xC = int.Parse(inputs[7]); 38 | int yC = int.Parse(inputs[8]); 39 | string D = inputs[9]; 40 | int xD = int.Parse(inputs[10]); 41 | int yD = int.Parse(inputs[11]); 42 | 43 | double AngleA = Math.Round(Angle(xD, yD, xA, yA, xB, yB), 4); 44 | double AngleB = Math.Round(Angle(xA, yA, xB, yB, xC, yC), 4); 45 | double AngleC = Math.Round(Angle(xB, yB, xC, yC, xD, yD), 4); 46 | double AngleD = Math.Round(Angle(xC, yC, xD, yD, xA, yA), 4); 47 | double LengthAB = Math.Round(Length(xA, yA, xB, yB), 4); 48 | double LengthBC = Math.Round(Length(xB, yB, xC, yC), 4); 49 | double LengthCD = Math.Round(Length(xC, yC, xD, yD), 4); 50 | double LengthDA = Math.Round(Length(xD, yD, xA, yA), 4); 51 | 52 | if ((AngleA == AngleB) && (AngleB == AngleC) && (AngleC == AngleD)) 53 | { 54 | if ((LengthAB == LengthBC) && (LengthBC == LengthCD) && (LengthCD == LengthDA)) 55 | Console.WriteLine("{0}{1}{2}{3} is a square.", A, B, C, D); 56 | else 57 | Console.WriteLine("{0}{1}{2}{3} is a rectangle.", A, B, C, D); 58 | } 59 | else if ((LengthAB == LengthBC) && (LengthBC == LengthCD) && (LengthCD == LengthDA)) 60 | Console.WriteLine("{0}{1}{2}{3} is a rhombus.", A, B, C, D); 61 | else if ((LengthAB == LengthCD) && (LengthBC == LengthDA) && (AngleA == AngleC) && (AngleB == AngleD)) 62 | Console.WriteLine("{0}{1}{2}{3} is a parallelogram.", A, B, C, D); 63 | else 64 | Console.WriteLine("{0}{1}{2}{3} is a quadrilateral.", A, B, C, D); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Surface.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | vector> cache; 10 | 11 | int getLakeSize(const vector>& grid, int x, int y) 12 | { 13 | if (cache[y][x] != 0) 14 | return cache[y][x]; 15 | 16 | int waterCount = 0; 17 | vector> visited(grid.size(), vector(grid[0].size(), false)); 18 | 19 | vector> visitedCells; 20 | 21 | queue> fringe; 22 | fringe.push({x, y}); 23 | while (!fringe.empty()) 24 | { 25 | pair cell = fringe.front(); 26 | fringe.pop(); 27 | 28 | if (!visited[cell.second][cell.first]) 29 | { 30 | visited[cell.second][cell.first] = true; 31 | if (grid[cell.second][cell.first]) 32 | { 33 | visitedCells.push_back({cell.first, cell.second}); 34 | waterCount += 1; 35 | 36 | if (cell.first > 0) 37 | { 38 | if (!visited[cell.second][cell.first-1]) 39 | fringe.push({cell.first-1, cell.second}); 40 | } 41 | if (cell.second > 0) 42 | { 43 | if (!visited[cell.second-1][cell.first]) 44 | fringe.push({cell.first, cell.second-1}); 45 | } 46 | if (cell.first < grid[0].size()-1) 47 | { 48 | if (!visited[cell.second][cell.first+1]) 49 | fringe.push({cell.first+1, cell.second}); 50 | } 51 | if (cell.second < grid.size()-1) 52 | { 53 | if (!visited[cell.second+1][cell.first]) 54 | fringe.push({cell.first, cell.second+1}); 55 | } 56 | } 57 | } 58 | } 59 | 60 | for (auto& cell : visitedCells) 61 | cache[cell.second][cell.first] = waterCount; 62 | 63 | return waterCount; 64 | } 65 | 66 | int main() 67 | { 68 | vector answers; 69 | vector> grid; 70 | 71 | int L; 72 | cin >> L; cin.ignore(); 73 | int H; 74 | cin >> H; cin.ignore(); 75 | for (int i = 0; i < H; i++) { 76 | string row; 77 | cin >> row; cin.ignore(); 78 | 79 | grid.push_back({}); 80 | for (char c : row) 81 | { 82 | if (c == '#') 83 | grid.back().push_back(false); 84 | else 85 | grid.back().push_back(true); 86 | } 87 | } 88 | 89 | cache.resize(grid.size(), vector(grid[0].size(), 0)); 90 | 91 | int N; 92 | cin >> N; cin.ignore(); 93 | for (int i = 0; i < N; i++) { 94 | int X; 95 | int Y; 96 | cin >> X >> Y; cin.ignore(); 97 | 98 | answers.push_back(getLakeSize(grid, X, Y)); 99 | } 100 | for (int i = 0; i < N; i++) { 101 | cout << answers[i] << endl; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Community Puzzles/These Romans are crazy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int decode(char* str) 4 | { 5 | int result = 0; 6 | int index = strlen(str); 7 | char lastChar = 0; 8 | 9 | while (index > 0) { 10 | index--; 11 | 12 | if (str[index] == 'M') { 13 | result += 1000; 14 | } 15 | else if (str[index] == 'D') { 16 | result += 500; 17 | } 18 | else if (str[index] == 'C') { 19 | if (lastChar == 'D' || lastChar == 'M') { 20 | result -= 100; 21 | } 22 | else { 23 | result += 100; 24 | } 25 | } 26 | else if (str[index] == 'L') { 27 | result += 50; 28 | } 29 | else if (str[index] == 'X') { 30 | if (lastChar == 'L' || lastChar == 'C') { 31 | result -= 10; 32 | } 33 | else { 34 | result += 10; 35 | } 36 | } 37 | else if (str[index] == 'V') { 38 | result += 5; 39 | } 40 | else if (str[index] == 'I') { 41 | if (lastChar == 'V' || lastChar == 'X') { 42 | result -= 1; 43 | } 44 | else { 45 | result += 1; 46 | } 47 | } 48 | 49 | lastChar = str[index]; 50 | } 51 | 52 | return result; 53 | } 54 | 55 | char rom[11]; 56 | char* encode(int num) 57 | { 58 | int index = 0; 59 | while (num > 0) { 60 | if (num >= 1000) { 61 | rom[index++] = 'M'; 62 | num -= 1000; 63 | } 64 | else if (num >= 900) { 65 | rom[index++] = 'C'; 66 | rom[index++] = 'M'; 67 | num -= 900; 68 | } 69 | else if (num >= 500) { 70 | rom[index++] = 'D'; 71 | num -= 500; 72 | } 73 | else if (num >= 400) { 74 | rom[index++] = 'C'; 75 | rom[index++] = 'D'; 76 | num -= 400; 77 | } 78 | else if (num >= 100) { 79 | rom[index++] = 'C'; 80 | num -= 100; 81 | } 82 | else if (num >= 90) { 83 | rom[index++] = 'X'; 84 | rom[index++] = 'C'; 85 | num -= 90; 86 | } 87 | else if (num >= 50) { 88 | rom[index++] = 'L'; 89 | num -= 50; 90 | } 91 | else if (num >= 40) { 92 | rom[index++] = 'X'; 93 | rom[index++] = 'L'; 94 | num -= 40; 95 | } 96 | else if (num >= 10) { 97 | rom[index++] = 'X'; 98 | num -= 10; 99 | } 100 | else if (num >= 9) { 101 | rom[index++] = 'I'; 102 | rom[index++] = 'X'; 103 | num -= 9; 104 | } 105 | else if (num >= 5) { 106 | rom[index++] = 'V'; 107 | num -= 5; 108 | } 109 | else if (num >= 4) { 110 | rom[index++] = 'I'; 111 | rom[index++] = 'V'; 112 | num -= 4; 113 | } 114 | else if (num >= 1) { 115 | rom[index++] = 'I'; 116 | num -= 1; 117 | } 118 | } 119 | 120 | rom[index] = 0; 121 | return rom; 122 | } 123 | 124 | int main() 125 | { 126 | char rom1[11]; 127 | scanf("%s", rom1); 128 | char rom2[11]; 129 | scanf("%s", rom2); 130 | 131 | printf("%s\n", encode(decode(rom1) + decode(rom2))); 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Skynet strikes back.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct Node 12 | { 13 | int id; 14 | vector connections; 15 | bool exitNode = false; 16 | bool visited = false; 17 | }; 18 | 19 | vector nodes; 20 | 21 | vector getGatewayLinks(Node* node) 22 | { 23 | vector nodes; 24 | for (auto& connection : node->connections) 25 | { 26 | if (connection->exitNode) 27 | nodes.push_back(connection); 28 | } 29 | 30 | return nodes; 31 | } 32 | 33 | pair findBest(Node* start) 34 | { 35 | for (auto& node : nodes) 36 | node.visited = false; 37 | 38 | bool firstFound = false; 39 | pair backupPlan; 40 | 41 | queue fringe; 42 | fringe.push(start); 43 | while (!fringe.empty()) 44 | { 45 | Node* node = fringe.front(); 46 | fringe.pop(); 47 | 48 | node->visited = true; 49 | 50 | vector gatewayLinks = getGatewayLinks(node); 51 | 52 | if (gatewayLinks.size() > 1) 53 | { 54 | return {node->id, gatewayLinks[0]->id}; 55 | } 56 | else if (gatewayLinks.size() == 1) 57 | { 58 | if (!firstFound) 59 | { 60 | firstFound = true; 61 | backupPlan = {node->id, gatewayLinks[0]->id}; 62 | } 63 | 64 | for (auto& neighbor : node->connections) 65 | { 66 | if (!neighbor->visited) 67 | fringe.push(neighbor); 68 | } 69 | } 70 | else // gatewayLinks.size() == 0 71 | { 72 | if (!firstFound) 73 | { 74 | for (auto& neighbor : node->connections) 75 | { 76 | if (!neighbor->visited) 77 | fringe.push(neighbor); 78 | } 79 | } 80 | } 81 | } 82 | 83 | if (firstFound) 84 | return backupPlan; 85 | else 86 | { 87 | cerr << "ERROR, no immediate thread, we should probably pick some link though" << endl; 88 | return {0, 0}; 89 | } 90 | } 91 | 92 | int main() 93 | { 94 | int N; // the total number of nodes in the level, including the gateways 95 | int L; // the number of links 96 | int E; // the number of exit gateways 97 | cin >> N >> L >> E; cin.ignore(); 98 | 99 | assert(N > 0); 100 | nodes.resize(N); 101 | for (int i = 0; i < N; ++i) 102 | nodes[i].id = i; 103 | 104 | for (int i = 0; i < L; i++) { 105 | int N1; // N1 and N2 defines a link between these nodes 106 | int N2; 107 | cin >> N1 >> N2; cin.ignore(); 108 | 109 | nodes[N1].connections.push_back(&nodes[N2]); 110 | nodes[N2].connections.push_back(&nodes[N1]); 111 | } 112 | for (int i = 0; i < E; i++) { 113 | int EI; // the index of a gateway node 114 | cin >> EI; cin.ignore(); 115 | 116 | nodes[EI].exitNode = true; 117 | } 118 | 119 | // game loop 120 | while (1) { 121 | int SI; // The index of the node on which the Skynet agent is positioned this turn 122 | cin >> SI; cin.ignore(); 123 | 124 | pair connection = findBest(&nodes[SI]); 125 | cout << connection.first << " " << connection.second << endl; 126 | 127 | // Remove the connection (so the algorithm doesn't try to destroy it twice) 128 | nodes[connection.first].connections.erase(find(nodes[connection.first].connections.begin(), nodes[connection.first].connections.end(), &nodes[connection.second])); 129 | nodes[connection.second].connections.erase(find(nodes[connection.second].connections.begin(), nodes[connection.second].connections.end(), &nodes[connection.first])); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Heat Detector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | int W; // width of the building. 15 | int H; // height of the building. 16 | cin >> W >> H; cin.ignore(); 17 | int N; // maximum number of turns before game over. 18 | cin >> N; cin.ignore(); 19 | int X0; 20 | int Y0; 21 | cin >> X0 >> Y0; cin.ignore(); 22 | 23 | int left = X0; 24 | int top = Y0; 25 | int width; 26 | int height; 27 | bool firstTime = true; 28 | 29 | // game loop 30 | while (1) { 31 | string BOMB_DIR; // the direction of the bombs from batman's current location (U, UR, R, DR, D, DL, L or UL) 32 | cin >> BOMB_DIR; cin.ignore(); 33 | 34 | if (firstTime) 35 | { 36 | if (BOMB_DIR == "U") 37 | { 38 | width = 0; 39 | height = Y0; 40 | } 41 | else if (BOMB_DIR == "D") 42 | { 43 | width = 0; 44 | height = H - Y0; 45 | } 46 | else if (BOMB_DIR == "L") 47 | { 48 | width = X0; 49 | height = 0; 50 | } 51 | else if (BOMB_DIR == "R") 52 | { 53 | width = W - X0; 54 | height = 0; 55 | } 56 | if (BOMB_DIR == "UL") 57 | { 58 | width = X0; 59 | height = Y0; 60 | } 61 | else if (BOMB_DIR == "UR") 62 | { 63 | width = W - X0; 64 | height = Y0; 65 | } 66 | else if (BOMB_DIR == "DL") 67 | { 68 | width = X0; 69 | height = H - Y0; 70 | } 71 | else if (BOMB_DIR == "DR") 72 | { 73 | width = W - X0; 74 | height = H - Y0; 75 | } 76 | 77 | firstTime = false; 78 | } 79 | 80 | if (BOMB_DIR == "D") 81 | { 82 | Y0 = top + (int)ceil(height/2.0); 83 | } 84 | else if (BOMB_DIR == "U") 85 | { 86 | Y0 = top - (int)ceil(height/2.0); 87 | } 88 | else if (BOMB_DIR == "L") 89 | { 90 | X0 = left - (int)ceil(width/2.0); 91 | } 92 | else if (BOMB_DIR == "R") 93 | { 94 | X0 = left + (int)ceil(width/2.0); 95 | } 96 | else if (BOMB_DIR == "UL") 97 | { 98 | X0 = left - (int)ceil(width/2.0); 99 | Y0 = top - (int)ceil(height/2.0); 100 | } 101 | else if (BOMB_DIR == "UR") 102 | { 103 | X0 = left + (int)ceil(width/2.0); 104 | Y0 = top - (int)ceil(height/2.0); 105 | } 106 | else if (BOMB_DIR == "DL") 107 | { 108 | X0 = left - (int)ceil(width/2.0); 109 | Y0 = top + (int)ceil(height/2.0); 110 | } 111 | else if (BOMB_DIR == "DR") 112 | { 113 | X0 = left + (int)ceil(width/2.0); 114 | Y0 = top + (int)ceil(height/2.0); 115 | } 116 | 117 | if (BOMB_DIR == "UL" || BOMB_DIR == "UR" || BOMB_DIR == "DL" || BOMB_DIR == "DR") 118 | { 119 | left = X0; 120 | top = Y0; 121 | width = width/2; 122 | height = height/2; 123 | } 124 | else if (BOMB_DIR == "U" || BOMB_DIR == "D") 125 | { 126 | top = Y0; 127 | width = 1; 128 | height = height/2; 129 | } 130 | else if (BOMB_DIR == "L" || BOMB_DIR == "R") 131 | { 132 | left = X0; 133 | width = width/2; 134 | height = 1; 135 | } 136 | 137 | cout << X0 << " " << Y0 << endl; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Optimization/Code vs Zombies.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct Human 9 | { 10 | Human(int id_, int x_, int y_) : id(id_), x(x_), y(y_) {} 11 | 12 | int id; 13 | int x; 14 | int y; 15 | }; 16 | 17 | struct Zombie 18 | { 19 | Zombie(int id_, int x_, int y_, int nextX_, int nextY_) : id(id_), x(x_), y(y_), nextX(nextX_), nextY(nextY_) {} 20 | 21 | int id; 22 | int x; 23 | int y; 24 | int nextX; 25 | int nextY; 26 | }; 27 | 28 | int dist(int x1, int y1, int x2, int y2) 29 | { 30 | return sqrt(pow(x1-x2, 2) + pow(y1-y2, 2)); 31 | } 32 | 33 | int main() 34 | { 35 | // game loop 36 | while (1) { 37 | vector humans; 38 | vector zombies; 39 | 40 | int playerX; 41 | int playerY; 42 | cin >> playerX >> playerY; cin.ignore(); 43 | int humanCount; 44 | cin >> humanCount; cin.ignore(); 45 | for (int i = 0; i < humanCount; i++) { 46 | int humanId; 47 | int humanX; 48 | int humanY; 49 | cin >> humanId >> humanX >> humanY; cin.ignore(); 50 | humans.emplace_back(humanId, humanX, humanY); 51 | } 52 | int zombieCount; 53 | cin >> zombieCount; cin.ignore(); 54 | for (int i = 0; i < zombieCount; i++) { 55 | int zombieId; 56 | int zombieX; 57 | int zombieY; 58 | int zombieXNext; 59 | int zombieYNext; 60 | cin >> zombieId >> zombieX >> zombieY >> zombieXNext >> zombieYNext; cin.ignore(); 61 | zombies.emplace_back(zombieId, zombieX, zombieY, zombieXNext, zombieYNext); 62 | } 63 | 64 | // Find the human in greatest danger 65 | pair target; 66 | int minDist = numeric_limits::max(); 67 | for (auto& human : humans) 68 | { 69 | Zombie* closingZombie; 70 | int closestZombieDist = numeric_limits::max(); 71 | for (auto& zombie : zombies) 72 | { 73 | int zombieDist = dist(human.x, human.y, zombie.x, zombie.y); 74 | if (closestZombieDist > zombieDist) 75 | { 76 | closestZombieDist = zombieDist; 77 | closingZombie = &zombie; 78 | } 79 | } 80 | 81 | if (closestZombieDist < minDist) 82 | { 83 | int distance = dist(playerX, playerY, human.x, human.y); 84 | if (closestZombieDist / 400.0 >= (max(distance - 2000, 0)) / 1000.0) 85 | { 86 | target = {closingZombie->x, closingZombie->y}; 87 | minDist = closestZombieDist; 88 | } 89 | } 90 | } 91 | 92 | // Check if player is the closest to ALL zombies 93 | bool playerClosestToAllZombies = true; 94 | for (auto& zombie : zombies) 95 | { 96 | for (auto& human : humans) 97 | { 98 | if (dist(human.x, human.y, zombie.x, zombie.y) < dist(playerX, playerY, zombie.x, zombie.y)) 99 | { 100 | playerClosestToAllZombies = false; 101 | break; 102 | } 103 | } 104 | 105 | if (!playerClosestToAllZombies) 106 | break; 107 | } 108 | 109 | // When we are closest to all zombies, move to their center 110 | if (playerClosestToAllZombies) 111 | { 112 | double centerX = 0; 113 | double centerY = 0; 114 | for (auto& zombie : zombies) 115 | { 116 | centerX += zombie.x; 117 | centerY += zombie.y; 118 | } 119 | centerX /= zombies.size(); 120 | centerY /= zombies.size(); 121 | 122 | target = {centerX, centerY}; 123 | } 124 | 125 | cout << target.first << " " << target.second << endl; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Multiplayer Contests/2015-11-28 Code vs Zombies.cpp: -------------------------------------------------------------------------------- 1 | // Rank: 269/3963 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | struct Human 11 | { 12 | Human(int id_, int x_, int y_) : id(id_), x(x_), y(y_) {} 13 | 14 | int id; 15 | int x; 16 | int y; 17 | }; 18 | 19 | struct Zombie 20 | { 21 | Zombie(int id_, int x_, int y_, int nextX_, int nextY_) : id(id_), x(x_), y(y_), nextX(nextX_), nextY(nextY_) {} 22 | 23 | int id; 24 | int x; 25 | int y; 26 | int nextX; 27 | int nextY; 28 | }; 29 | 30 | int dist(int x1, int y1, int x2, int y2) 31 | { 32 | return sqrt(pow(x1-x2, 2) + pow(y1-y2, 2)); 33 | } 34 | 35 | int main() 36 | { 37 | // game loop 38 | while (1) { 39 | vector humans; 40 | vector zombies; 41 | 42 | int playerX; 43 | int playerY; 44 | cin >> playerX >> playerY; cin.ignore(); 45 | int humanCount; 46 | cin >> humanCount; cin.ignore(); 47 | for (int i = 0; i < humanCount; i++) { 48 | int humanId; 49 | int humanX; 50 | int humanY; 51 | cin >> humanId >> humanX >> humanY; cin.ignore(); 52 | humans.emplace_back(humanId, humanX, humanY); 53 | } 54 | int zombieCount; 55 | cin >> zombieCount; cin.ignore(); 56 | for (int i = 0; i < zombieCount; i++) { 57 | int zombieId; 58 | int zombieX; 59 | int zombieY; 60 | int zombieXNext; 61 | int zombieYNext; 62 | cin >> zombieId >> zombieX >> zombieY >> zombieXNext >> zombieYNext; cin.ignore(); 63 | zombies.emplace_back(zombieId, zombieX, zombieY, zombieXNext, zombieYNext); 64 | } 65 | 66 | // Find the human in greatest danger 67 | pair target; 68 | int minDist = numeric_limits::max(); 69 | for (auto& human : humans) 70 | { 71 | Zombie* closingZombie; 72 | int closestZombieDist = numeric_limits::max(); 73 | for (auto& zombie : zombies) 74 | { 75 | int zombieDist = dist(human.x, human.y, zombie.x, zombie.y); 76 | if (closestZombieDist > zombieDist) 77 | { 78 | closestZombieDist = zombieDist; 79 | closingZombie = &zombie; 80 | } 81 | } 82 | 83 | if (closestZombieDist < minDist) 84 | { 85 | int distance = dist(playerX, playerY, human.x, human.y); 86 | if (closestZombieDist / 400.0 >= (max(distance - 2000, 0)) / 1000.0) 87 | { 88 | target = {closingZombie->x, closingZombie->y}; 89 | minDist = closestZombieDist; 90 | } 91 | } 92 | } 93 | 94 | // Check if player is the closest to ALL zombies 95 | bool playerClosestToAllZombies = true; 96 | for (auto& zombie : zombies) 97 | { 98 | for (auto& human : humans) 99 | { 100 | if (dist(human.x, human.y, zombie.x, zombie.y) < dist(playerX, playerY, zombie.x, zombie.y)) 101 | { 102 | playerClosestToAllZombies = false; 103 | break; 104 | } 105 | } 106 | 107 | if (!playerClosestToAllZombies) 108 | break; 109 | } 110 | 111 | // When we are closest to all zombies, move to their center 112 | if (playerClosestToAllZombies) 113 | { 114 | double centerX = 0; 115 | double centerY = 0; 116 | for (auto& zombie : zombies) 117 | { 118 | centerX += zombie.x; 119 | centerY += zombie.y; 120 | } 121 | centerX /= zombies.size(); 122 | centerY /= zombies.size(); 123 | 124 | target = {centerX, centerY}; 125 | } 126 | 127 | cout << target.first << " " << target.second << endl; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /SingePlayer/Very Hard/The Resistance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct TreeNode 10 | { 11 | TreeNode* dotChild = NULL; 12 | TreeNode* dashChild = NULL; 13 | long long valid = 0; 14 | }; 15 | 16 | string encode(string input) 17 | { 18 | string result; 19 | for (auto& c : input) 20 | { 21 | switch (c) 22 | { 23 | case 'A': result += ".-"; break; 24 | case 'B': result += "-..."; break; 25 | case 'C': result += "-.-."; break; 26 | case 'D': result += "-.."; break; 27 | case 'E': result += "."; break; 28 | case 'F': result += "..-."; break; 29 | case 'G': result += "--."; break; 30 | case 'H': result += "...."; break; 31 | case 'I': result += ".."; break; 32 | case 'J': result += ".---"; break; 33 | case 'K': result += "-.-"; break; 34 | case 'L': result += ".-.."; break; 35 | case 'M': result += "--"; break; 36 | case 'N': result += "-."; break; 37 | case 'O': result += "---"; break; 38 | case 'P': result += ".--."; break; 39 | case 'Q': result += "--.-"; break; 40 | case 'R': result += ".-."; break; 41 | case 'S': result += "..."; break; 42 | case 'T': result += "-"; break; 43 | case 'U': result += "..-"; break; 44 | case 'V': result += "...-"; break; 45 | case 'W': result += ".--"; break; 46 | case 'X': result += "-..-"; break; 47 | case 'Y': result += "-.--"; break; 48 | case 'Z': result += "--.."; break; 49 | default: throw runtime_error("ERROR"); 50 | } 51 | } 52 | 53 | return result; 54 | } 55 | 56 | void insert(TreeNode* node, string dictWord, long long pos = 0) 57 | { 58 | while (pos < dictWord.size()) { 59 | if (dictWord[pos] == '.') { 60 | if (node->dotChild == NULL) 61 | node->dotChild = new TreeNode(); 62 | 63 | node = node->dotChild; 64 | } 65 | else { 66 | if (node->dashChild == NULL) 67 | node->dashChild = new TreeNode(); 68 | 69 | node = node->dashChild; 70 | } 71 | 72 | pos += 1; 73 | } 74 | 75 | node->valid += 1; 76 | } 77 | 78 | void deleteTree(TreeNode* node) 79 | { 80 | if (node->dotChild != NULL) 81 | deleteTree(node->dotChild); 82 | 83 | if (node->dashChild != NULL) 84 | deleteTree(node->dashChild); 85 | 86 | delete node; 87 | } 88 | 89 | string L; 90 | TreeNode* root = new TreeNode(); 91 | map cache; 92 | 93 | long long solve(long long pos) 94 | { 95 | TreeNode* node = root; 96 | long long solutions = 0; 97 | while (pos < L.size()) { 98 | if ((L[pos] == '.') && (node->dotChild != NULL)) 99 | node = node->dotChild; 100 | else if ((L[pos] == '-') && (node->dashChild != NULL)) 101 | node = node->dashChild; 102 | else 103 | break; 104 | 105 | if (node->valid > 0) { 106 | if (pos == L.size()-1) 107 | solutions += node->valid; 108 | else { 109 | if (cache.find(pos+1) != cache.end()) { 110 | solutions += node->valid * cache[pos+1]; 111 | } 112 | else { 113 | long long res = solve(pos+1); 114 | if (res > 0) { 115 | solutions += node->valid * res; 116 | cache[pos+1] = res; 117 | } 118 | } 119 | } 120 | } 121 | 122 | ++pos; 123 | } 124 | 125 | return solutions; 126 | } 127 | 128 | int main() 129 | { 130 | cin >> L; cin.ignore(); 131 | int N; 132 | cin >> N; cin.ignore(); 133 | for (int i = 0; i < N; i++) { 134 | string W; 135 | cin >> W; cin.ignore(); 136 | insert(root, encode(W)); 137 | } 138 | 139 | cout << solve(0) << endl; 140 | 141 | deleteTree(root); 142 | } 143 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Winamax Sponsored Challenge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int getCardValue(string card) 10 | { 11 | int val = atoi(card.substr(0, card.length()-1).c_str()); 12 | if (val > 0) 13 | return val; 14 | else 15 | { 16 | if (card[0] == 'J') 17 | return 11; 18 | else if (card[0] == 'Q') 19 | return 12; 20 | else if (card[0] == 'K') 21 | return 13; 22 | else if (card[0] == 'A') 23 | return 14; 24 | } 25 | } 26 | 27 | int getWinner(string card1, string card2) 28 | { 29 | if (getCardValue(card1) > getCardValue(card2)) 30 | return 1; 31 | else if (getCardValue(card1) < getCardValue(card2)) 32 | return 2; 33 | else 34 | return 0; 35 | } 36 | 37 | int main() 38 | { 39 | deque cardsP1; 40 | deque cardsP2; 41 | deque cardsOnTableP1; 42 | deque cardsOnTableP2; 43 | 44 | int n; // the number of cards for player 1 45 | cin >> n; cin.ignore(); 46 | for (int i = 0; i < n; i++) { 47 | string cardp1; // the n cards of player 1 48 | cin >> cardp1; cin.ignore(); 49 | 50 | cardsP1.push_back(cardp1); 51 | } 52 | int m; // the number of cards for player 2 53 | cin >> m; cin.ignore(); 54 | for (int i = 0; i < m; i++) { 55 | string cardp2; // the m cards of player 2 56 | cin >> cardp2; cin.ignore(); 57 | 58 | cardsP2.push_back(cardp2); 59 | } 60 | 61 | int rounds = 0; 62 | while (true) 63 | { 64 | // The game ends when one player no longer has cards 65 | if (cardsP1.empty()) 66 | { 67 | cout << 2 << " " << rounds << endl; 68 | return 0; 69 | } 70 | else if (cardsP2.empty()) 71 | { 72 | cout << 1 << " " << rounds << endl; 73 | return 0; 74 | } 75 | 76 | bool playingWar; 77 | do 78 | { 79 | playingWar = false; 80 | 81 | // Each player draws a card 82 | cardsOnTableP1.push_back(cardsP1.front()); 83 | cardsOnTableP2.push_back(cardsP2.front()); 84 | cardsP1.pop_front(); 85 | cardsP2.pop_front(); 86 | 87 | // Play the round 88 | int roundWinner = getWinner(cardsOnTableP1.back(), cardsOnTableP2.back()); 89 | cerr << cardsOnTableP1.back() << " " << cardsOnTableP2.back() << " " << roundWinner << endl; 90 | if (roundWinner == 1) 91 | { 92 | for (auto& card : cardsOnTableP1) 93 | cardsP1.push_back(card); 94 | 95 | for (auto& card : cardsOnTableP2) 96 | cardsP1.push_back(card); 97 | 98 | cardsOnTableP1.clear(); 99 | cardsOnTableP2.clear(); 100 | } 101 | else if (roundWinner == 2) 102 | { 103 | for (auto& card : cardsOnTableP1) 104 | cardsP2.push_back(card); 105 | 106 | for (auto& card : cardsOnTableP2) 107 | cardsP2.push_back(card); 108 | 109 | cardsOnTableP1.clear(); 110 | cardsOnTableP2.clear(); 111 | } 112 | else // war! 113 | { 114 | // If we don't have enough cards => draw 115 | if ((cardsP1.size() < 4) || (cardsP2.size() < 4)) 116 | { 117 | cout << "PAT" << endl; 118 | return 0; 119 | } 120 | 121 | // Place 3 cards face down 122 | for (int i = 0; i < 3; ++i) 123 | { 124 | cardsOnTableP1.push_back(cardsP1.front()); 125 | cardsOnTableP2.push_back(cardsP2.front()); 126 | cardsP1.pop_front(); 127 | cardsP2.pop_front(); 128 | } 129 | 130 | // Draw the next cards 131 | playingWar = true; 132 | } 133 | } while (playingWar); 134 | 135 | rounds++; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Mars Lander - Level 2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | /** 9 | * Auto-generated code below aims at helping you parse 10 | * the standard input according to the problem statement. 11 | **/ 12 | int main() 13 | { 14 | double g = -3.711; 15 | vector> land; 16 | 17 | int N; // the number of points used to draw the surface of Mars. 18 | cin >> N; cin.ignore(); 19 | for (int i = 0; i < N; i++) { 20 | int LAND_X; // X coordinate of a surface point. (0 to 6999) 21 | int LAND_Y; // Y coordinate of a surface point. By linking all the points together in a sequential fashion, you form the surface of Mars. 22 | cin >> LAND_X >> LAND_Y; cin.ignore(); 23 | 24 | land.push_back({LAND_X, LAND_Y}); 25 | } 26 | 27 | // Search the landing spot 28 | pair landingSpot; 29 | for (int i = 1; i < land.size(); ++i) 30 | { 31 | if (land[i-1].second == land[i].second) 32 | { 33 | landingSpot = {(land[i-1].first + land[i].first) / 2, land[i].second}; 34 | break; 35 | } 36 | } 37 | 38 | // Find the maximum height 39 | int maxHeight = 0; 40 | for (int i = 0; i < land.size(); ++i) 41 | maxHeight = max(maxHeight, land[i].second); 42 | 43 | // game loop 44 | while (1) { 45 | int X; 46 | int Y; 47 | int HS; // the horizontal speed (in m/s), can be negative. 48 | int VS; // the vertical speed (in m/s), can be negative. 49 | int F; // the quantity of remaining fuel in liters. 50 | int R; // the rotation angle in degrees (-90 to 90). 51 | int P; // the thrust power (0 to 4). 52 | cin >> X >> Y >> HS >> VS >> F >> R >> P; cin.ignore(); 53 | 54 | 55 | // VSpeed = VSpeed + (Power * sin(Angle)) + g 56 | // HSpeed = HSpeed + (Power * cos(Angle)) 57 | // X = X + HSpeed 58 | // Y = Y + VSpeed 59 | // Fuel = Fuel - Power 60 | 61 | // Stay above max height when going to landing spot 62 | if (X < landingSpot.first - 400) 63 | { 64 | // Calculate the height of peaks between us and the landing zone 65 | maxHeight = landingSpot.second; 66 | for (int i = 0; i < land.size(); ++i) 67 | { 68 | if ((land[i].first < landingSpot.first - 400) && (land[i].first > X)) 69 | maxHeight = max(maxHeight, land[i].second); 70 | } 71 | 72 | if (HS < 20) 73 | R = -20; 74 | 75 | if (HS >= 20) 76 | R = 30; 77 | else if (HS <= -20) 78 | R = -30; 79 | 80 | if (Y + 10*VS < Y - landingSpot.second) 81 | P = 4; 82 | else 83 | P = min(max(-VS - 36, 0), 4); 84 | 85 | // Don't go below peaks 86 | if ((Y - VS*VS <= maxHeight) /*&& (maxHeight != landingSpot.second)*/ 87 | && (X < landingSpot.first - 1000)) 88 | { 89 | P = 4; 90 | R = min(max(R, -3), 3); 91 | } 92 | } 93 | else if (X > landingSpot.first + 400) 94 | { 95 | // Calculate the height of peaks between us and the landing zone 96 | maxHeight = landingSpot.second; 97 | for (int i = 0; i < land.size(); ++i) 98 | { 99 | if ((land[i].first > landingSpot.first + 400) && (land[i].first < X)) 100 | maxHeight = max(maxHeight, land[i].second); 101 | } 102 | 103 | if (HS > -20) 104 | R = 20; 105 | 106 | if (HS >= 20) 107 | R = 30; 108 | else if (HS <= -20) 109 | R = -30; 110 | 111 | if ((VS < 0) && (10*VS < Y - landingSpot.second)) 112 | P = 4; 113 | else 114 | P = min(max(-VS - 36, 0), 4); 115 | 116 | // Don't go below peaks 117 | if ((Y - VS*VS <= maxHeight) /*&& (maxHeight != landingSpot.second)*/ 118 | && (X > landingSpot.first + 1000)) 119 | { 120 | P = 4; 121 | R = min(max(R, -3), 3); 122 | } 123 | } 124 | else 125 | { 126 | // HS = 50 => Angle = 45 127 | // HS = 0 => Angle = 0 128 | // HS = -50 => Angle = -45 129 | R = min(max((int)(HS / 30.0 * 45.0), -90), 90); 130 | 131 | // Angle = 45 => P = 4 132 | // Angle = 0 => P >= 0 133 | P = min(max(-VS - 30, max(abs((int)((R/45.0)*4)), 0)), 4); 134 | } 135 | 136 | // Angle == 0 when landing 137 | if (Y - landingSpot.second <= ((abs(2*R / 15) + 1) * -VS)) 138 | R = 0; 139 | 140 | // Emergency landing 141 | if (((R / 15) + 1) * P >= F) 142 | R = 0; 143 | 144 | // Set the wanted rotation and power 145 | cout << R << " " << P << endl; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /SingePlayer/Hard/The Labyrinth.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int R; // number of rows. 12 | int C; // number of columns. 13 | int A; // number of rounds between the time the alarm countdown is activated and the time the alarm goes off. 14 | 15 | struct Position 16 | { 17 | int x; 18 | int y; 19 | }; 20 | 21 | vector getNeighbors(vector>& graph, Position target) 22 | { 23 | if (graph[target.y][target.x] == '?') 24 | return {}; 25 | else 26 | { 27 | vector neighbors; 28 | 29 | if (graph[target.y][target.x-1] != '#') 30 | neighbors.push_back({target.x-1, target.y}); 31 | if (graph[target.y][target.x+1] != '#') 32 | neighbors.push_back({target.x+1, target.y}); 33 | if (graph[target.y-1][target.x] != '#') 34 | neighbors.push_back({target.x, target.y-1}); 35 | if (graph[target.y+1][target.x] != '#') 36 | neighbors.push_back({target.x, target.y+1}); 37 | 38 | return neighbors; 39 | } 40 | } 41 | 42 | vector dijkstra(vector>& graph, Position source, char goal) 43 | { 44 | auto dist = vector>(R, vector(C, numeric_limits::max())); 45 | auto prev = vector>(R, vector(C, {numeric_limits::max(), numeric_limits::max()})); 46 | vector unvisited; 47 | 48 | // Initialization 49 | dist[source.y][source.x] = 0; 50 | for (int y = 0; y < R; ++y) 51 | { 52 | for (int x = 0; x < C; ++x) 53 | unvisited.push_back({x, y}); 54 | } 55 | 56 | while (!unvisited.empty()) 57 | { 58 | // Find node with smallest distance 59 | vector::iterator minIt = unvisited.begin(); 60 | int minDist = numeric_limits::max(); 61 | for (auto it = unvisited.begin(); it != unvisited.end(); ++it) 62 | { 63 | if (dist[it->y][it->x] < minDist) 64 | { 65 | minDist = dist[it->y][it->x]; 66 | minIt = it; 67 | } 68 | } 69 | 70 | // Return an empty list when there is no way to get to the goal 71 | if (minDist == numeric_limits::max()) 72 | return {}; 73 | 74 | // Remove and return best vertex 75 | Position target = *minIt; 76 | unvisited.erase(minIt); 77 | 78 | // Check if goal node 79 | if (graph[target.y][target.x] == goal) 80 | { 81 | stack pathStack; 82 | Position node = target; 83 | while (prev[node.y][node.x].x != numeric_limits::max() && prev[node.y][node.x].y != numeric_limits::max()) 84 | { 85 | pathStack.push(node); 86 | node = prev[node.y][node.x]; 87 | } 88 | 89 | vector path; 90 | while (!pathStack.empty()) 91 | { 92 | path.push_back(pathStack.top()); 93 | pathStack.pop(); 94 | } 95 | 96 | return path; 97 | } 98 | 99 | vector neighbors = getNeighbors(graph, target); 100 | for (Position& neighbor : neighbors) 101 | { 102 | int alt = dist[target.y][target.x] + 1; 103 | if (alt < dist[neighbor.y][neighbor.x]) 104 | { 105 | dist[neighbor.y][neighbor.x] = alt; 106 | prev[neighbor.y][neighbor.x] = target; 107 | } 108 | } 109 | } 110 | 111 | return {}; 112 | } 113 | 114 | int main() 115 | { 116 | cin >> R >> C >> A; cin.ignore(); 117 | 118 | bool controlFound = false; 119 | bool controlVisited = false; 120 | 121 | // game loop 122 | while (1) { 123 | vector> grid; 124 | 125 | int KR; // row where Kirk is located. 126 | int KC; // column where Kirk is located. 127 | cin >> KR >> KC; cin.ignore(); 128 | for (int i = 0; i < R; i++) { 129 | string ROW; // C of the characters in '#.TC?' (i.e. one line of the ASCII maze). 130 | cin >> ROW; cin.ignore(); 131 | 132 | grid.push_back({}); 133 | for (char c : ROW) 134 | grid.back().push_back(c); 135 | } 136 | 137 | if (grid[KR][KC] == 'C') 138 | controlVisited = true; 139 | 140 | vector path; 141 | if (controlVisited) 142 | { 143 | path = dijkstra(grid, {KC, KR}, 'T'); 144 | } 145 | else 146 | { 147 | path = dijkstra(grid, {KC, KR}, 'C'); 148 | if (path.empty()) 149 | path = dijkstra(grid, {KC, KR}, '?'); 150 | } 151 | assert(!path.empty()); 152 | 153 | if (path[0].x > KC) 154 | cout << "RIGHT" << endl; 155 | else if (path[0].x < KC) 156 | cout << "LEFT" << endl; 157 | else if (path[0].y > KR) 158 | cout << "DOWN" << endl; 159 | else 160 | cout << "UP" << endl; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Optimization/ CodinGame Sponsored Contest.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | width = int(input()) 4 | height = int(input()) 5 | players = int(input()) 6 | 7 | class Player: 8 | def __init__(self, x, y): 9 | self.x = x 10 | self.y = y 11 | 12 | DIR = {'UP' : 'C', 'RIGHT' : 'A', 'DOWN' : 'D', 'LEFT' : 'E', 'STAY' : 'B'} 13 | 14 | grid = [['?' for x in range(width)] for y in range(height)] 15 | enemies = [Player(-1,-1) for e in range(players-1)] 16 | player = Player(-1,-1) 17 | 18 | def enemyAtPos(x, y): 19 | for e in enemies: 20 | if x == e.x and y == e.y: 21 | return True 22 | return False 23 | 24 | def getPossibleMoves(x, y): 25 | possibleMoves = [] 26 | if grid[(y-1)%height][x] != '#': 27 | if not enemyAtPos(x, y-1) and not enemyAtPos(x, y-2) and not enemyAtPos(x-1, y-1) and not enemyAtPos(x+1, y-1): 28 | possibleMoves.append([x, (y-1)%height]) 29 | if grid[y][(x+1)%width] != '#': 30 | if not enemyAtPos(x+1, y) and not enemyAtPos(x+2, y) and not enemyAtPos(x+1, y-1) and not enemyAtPos(x+1, y+1): 31 | possibleMoves.append([(x+1)%width, y]) 32 | if grid[(y+1)%height][x] != '#': 33 | if not enemyAtPos(x, y+1) and not enemyAtPos(x, y+2) and not enemyAtPos(x-1, y+1) and not enemyAtPos(x+1, y+1): 34 | possibleMoves.append([x, (y+1)%height]) 35 | if grid[y][(x-1)%width] != '#': 36 | if not enemyAtPos(x-1, y) and not enemyAtPos(x-2, y) and not enemyAtPos(x-1, y-1) and not enemyAtPos(x-1, y+1): 37 | possibleMoves.append([(x-1)%width, y]) 38 | 39 | return possibleMoves 40 | 41 | def findNearestUnknown(): # BFS 42 | visited = [] 43 | fringe = [] # our queue 44 | fringe.append(((player.x, player.y), [])) 45 | 46 | while len(fringe) > 0: 47 | node = fringe.pop(0) # node is a tuple of a location, and the path to that location 48 | if node[0] in visited: 49 | continue 50 | 51 | visited += [node[0]] 52 | 53 | if grid[node[0][1]][node[0][0]] == '?': 54 | return node[1][0] # Return the location of the next step 55 | else: 56 | successors = getPossibleMoves(node[0][0], node[0][1]) 57 | for successor in successors: 58 | path = node[1] + [(successor[0], successor[1])] 59 | fringe.append(((successor[0], successor[1]), path)) 60 | 61 | return (player.x, player.y) 62 | 63 | def findAlternativeMove(): 64 | x, y = player.x, player.y 65 | 66 | # Move in any direction that makes us live at least one more turn 67 | if grid[(y-1)%height][x] != '#' and not enemyAtPos(x, y-1) and not enemyAtPos(x, y-2) and not enemyAtPos(x-1, y-1) and not enemyAtPos(x+1, y-1): 68 | return DIR['UP'] 69 | if grid[y][(x+1)%width] != '#' and not enemyAtPos(x+1, y) and not enemyAtPos(x+2, y) and not enemyAtPos(x+1, y-1) and not enemyAtPos(x+1, y+1): 70 | return DIR['RIGHT'] 71 | if grid[(y+1)%height][x] != '#' and not enemyAtPos(x, y+1) and not enemyAtPos(x, y+2) and not enemyAtPos(x-1, y+1) and not enemyAtPos(x+1, y+1): 72 | return DIR['DOWN'] 73 | if grid[y][(x-1)%width] != '#' and not enemyAtPos(x-1, y) and not enemyAtPos(x-2, y) and not enemyAtPos(x-1, y-1) and not enemyAtPos(x-1, y+1): 74 | return DIR['LEFT'] 75 | 76 | # We can't move, try to hit an enemy 77 | if enemyAtPos(x, y-1): 78 | return DIR['UP'] 79 | elif enemyAtPos(x+1, y): 80 | return DIR['RIGHT'] 81 | elif enemyAtPos(x, y+1): 82 | return DIR['DOWN'] 83 | elif enemyAtPos(x-1, y): 84 | return DIR['LEFT'] 85 | 86 | # There is no enemy next to us, just wait one turn 87 | return DIR['STAY'] 88 | 89 | # game loop 90 | while True: 91 | up = input() 92 | right = input() 93 | down = input() 94 | left = input() 95 | 96 | for i in range(players): 97 | playerX, playerY = [int(j) for j in input().split()] 98 | if i+1 == players: 99 | player.x, player.y = (playerX-1)%width, (playerY-1)%height 100 | else: 101 | enemies[i].x, enemies[i].y = (playerX-1)%width, (playerY-1)%height 102 | 103 | grid[player.y][player.x] = '_' 104 | grid[(player.y-1)%height][player.x] = up 105 | grid[(player.y+1)%height][player.x] = down 106 | grid[player.y][(player.x-1)%width] = left 107 | grid[player.y][(player.x+1)%width] = right 108 | 109 | # Debug information 110 | """ 111 | for y in range(height): 112 | for x in range(width): 113 | if enemyAtPos(x, y): 114 | print('@', end='', file=sys.stderr) 115 | else: 116 | if x == player.x and y == player.y: 117 | print('+', end='', file=sys.stderr) 118 | else: 119 | print(grid[y][x], end='', file=sys.stderr) 120 | print(file=sys.stderr) 121 | """ 122 | 123 | # Move towards unexplored areas 124 | x, y = findNearestUnknown() 125 | 126 | # Only make the suggested move when it doesn't get us killed 127 | if not enemyAtPos(x-1, y) and not enemyAtPos(x+1, y) and not enemyAtPos(x, y-1) and not enemyAtPos(x, y+1): 128 | if x == (player.x-1)%width: 129 | print(DIR['LEFT']) 130 | elif y == (player.y-1)%height: 131 | print(DIR['UP']) 132 | elif x == (player.x+1)%width: 133 | print(DIR['RIGHT']) 134 | elif y == (player.y+1)%height: 135 | print(DIR['DOWN']) 136 | else: 137 | print(DIR['STAY']) 138 | 139 | else: # We need an alternative move (try keeping us alive as long as possible) 140 | print(findAlternativeMove()) 141 | 142 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Vox Codei.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | struct Position 11 | { 12 | int x; 13 | int y; 14 | }; 15 | 16 | int calcDamage(vector>& grid, int x, int y) 17 | { 18 | int damage = 0; 19 | for (int i = x-1; i >= max(0, x-3); --i) 20 | { 21 | if (grid[y][i] == '#') 22 | break; 23 | else if (grid[y][i] == '@') 24 | damage++; 25 | } 26 | for (int i = x+1; i <= min(grid[0].size()-1, x+3); ++i) 27 | { 28 | if (grid[y][i] == '#') 29 | break; 30 | else if (grid[y][i] == '@') 31 | damage++; 32 | } 33 | for (int i = y-1; i >= max(0, y-3); --i) 34 | { 35 | if (grid[i][x] == '#') 36 | break; 37 | else if (grid[i][x] == '@') 38 | damage++; 39 | } 40 | for (int i = y+1; i <= min(grid.size()-1, y+3); ++i) 41 | { 42 | if (grid[i][x] == '#') 43 | break; 44 | else if (grid[i][x] == '@') 45 | damage++; 46 | } 47 | 48 | return damage; 49 | } 50 | 51 | void destroy(vector>& grid, int x, int y) 52 | { 53 | for (int i = x-1; i >= max(0, x-3); --i) 54 | { 55 | if (grid[y][i] == '#') 56 | break; 57 | else if (grid[y][i] == '@') 58 | grid[y][i] = '.'; 59 | } 60 | for (int i = x+1; i <= min(grid[0].size()-1, x+3); ++i) 61 | { 62 | if (grid[y][i] == '#') 63 | break; 64 | else if (grid[y][i] == '@') 65 | grid[y][i] = '.'; 66 | } 67 | for (int i = y-1; i >= max(0, y-3); --i) 68 | { 69 | if (grid[i][x] == '#') 70 | break; 71 | else if (grid[i][x] == '@') 72 | grid[i][x] = '.'; 73 | } 74 | for (int i = y+1; i <= min(grid.size()-1, y+3); ++i) 75 | { 76 | if (grid[i][x] == '#') 77 | break; 78 | else if (grid[i][x] == '@') 79 | grid[i][x] = '.'; 80 | } 81 | } 82 | 83 | int getRemainingTargets(vector>& grid) 84 | { 85 | int remainingTargets = 0; 86 | for (int y = 0; y < grid.size(); ++y) 87 | { 88 | for (int x = 0; x < grid[y].size(); ++x) 89 | { 90 | if (grid[y][x] == '@') 91 | remainingTargets++; 92 | } 93 | } 94 | 95 | return remainingTargets; 96 | } 97 | 98 | bool canWeWin(vector> grid, int x, int y, int bombs) 99 | { 100 | destroy(grid, x, y); 101 | 102 | // Where to place the bomb for maximum damage? 103 | int maxDamage = 0; 104 | for (int y = 0; y < grid.size(); ++y) 105 | { 106 | for (int x = 0; x < grid[y].size(); ++x) 107 | { 108 | if (grid[y][x] == '.') 109 | { 110 | int damage = calcDamage(grid, x, y); 111 | if ((damage > maxDamage)/* && canWeWin(grid, x, y, bombs-1)*/) 112 | maxDamage = damage; 113 | } 114 | } 115 | } 116 | 117 | // If the maximum damage multiplied with bombs we have left is not enough to destroy 118 | // all targets, then we should look for a different place to put our initial bomb 119 | if (maxDamage * bombs >= getRemainingTargets(grid)) 120 | return true; 121 | else 122 | return false; 123 | } 124 | 125 | int main() 126 | { 127 | vector> grid; 128 | vector> resultGrid; 129 | map, int> tickingBombs; 130 | 131 | int width; // width of the firewall grid 132 | int height; // height of the firewall grid 133 | cin >> width >> height; cin.ignore(); 134 | for (int i = 0; i < height; i++) { 135 | string mapRow; // one line of the firewall grid 136 | cin >> mapRow; cin.ignore(); 137 | 138 | grid.push_back({}); 139 | for (char c : mapRow) 140 | grid.back().push_back(c); 141 | } 142 | resultGrid = grid; 143 | 144 | // game loop 145 | while (1) { 146 | int rounds; // number of rounds left before the end of the game 147 | int bombs; // number of bombs left 148 | cin >> rounds >> bombs; cin.ignore(); 149 | 150 | // Tick tack 151 | for(auto it = tickingBombs.begin(); it != tickingBombs.end();) 152 | { 153 | it->second--; 154 | if (it->second == 0) 155 | { 156 | destroy(grid, it->first.first, it->first.second); 157 | it = tickingBombs.erase(it); 158 | } 159 | else 160 | ++it; 161 | } 162 | 163 | // Where to place the bomb for maximum damage? 164 | int maxDamage = 0; 165 | Position bombPos; 166 | for (int x = 0; x < width; ++x) 167 | { 168 | for (int y = 0; y < height; ++y) 169 | { 170 | if (resultGrid[y][x] == '.') 171 | { 172 | int damage = calcDamage(resultGrid, x, y); 173 | if ((damage > maxDamage) && canWeWin(resultGrid, x, y, bombs-1)) 174 | { 175 | maxDamage = damage; 176 | bombPos = {x, y}; 177 | } 178 | } 179 | } 180 | } 181 | 182 | // At the end of the game, wait until last bomb explodes 183 | if (maxDamage == 0) 184 | { 185 | cout << "WAIT" << endl; 186 | continue; 187 | } 188 | 189 | // Place the bomb 190 | if ((grid[bombPos.y][bombPos.x] == '.') 191 | && (tickingBombs.find({bombPos.x, bombPos.y}) == tickingBombs.end())) 192 | { 193 | destroy(resultGrid, bombPos.x, bombPos.y); 194 | tickingBombs[{bombPos.x, bombPos.y}] = 3; 195 | cout << bombPos.x << " " << bombPos.y << endl; 196 | } 197 | else 198 | cout << "WAIT" << endl; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /SingePlayer/Medium/Bender, a depressed robot.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct State 10 | { 11 | int x; 12 | int y; 13 | bool inverted = false; 14 | bool breakerMode = false; 15 | std::string direction = "SOUTH"; 16 | 17 | bool operator== (const State& state) const 18 | { 19 | return ((x == state.x) 20 | && (y == state.y) 21 | && (inverted == state.inverted) 22 | && (breakerMode == state.breakerMode) 23 | && (direction == state.direction)); 24 | } 25 | }; 26 | 27 | std::map, std::vector> visited; 28 | 29 | std::string directionToString(int x, int y) 30 | { 31 | if (x == 0) 32 | { 33 | if (y == 1) 34 | return "SOUTH"; 35 | else 36 | return "NORTH"; 37 | } 38 | else 39 | { 40 | if (x == 1) 41 | return "EAST"; 42 | else 43 | return "WEST"; 44 | } 45 | } 46 | 47 | std::string move(std::vector>& map, State& currentState) 48 | { 49 | std::vector> directions; 50 | if (currentState.inverted) 51 | directions = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; 52 | else 53 | directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; 54 | 55 | for (auto& direction : directions) 56 | { 57 | if ((map[currentState.y + direction.second][currentState.x + direction.first] != 'X') 58 | && (map[currentState.y + direction.second][currentState.x + direction.first] != '#')) 59 | { 60 | currentState.x += direction.first; 61 | currentState.y += direction.second; 62 | currentState.direction = directionToString(direction.first, direction.second); 63 | return currentState.direction; 64 | } 65 | } 66 | } 67 | 68 | std::string makeMovement(int x, int y, std::vector>& map, State& currentState) 69 | { 70 | if (map[currentState.y+y][currentState.x+x] == 'X') 71 | { 72 | if (currentState.breakerMode) 73 | { 74 | map[currentState.y+y][currentState.x+x] = ' '; 75 | visited.clear(); 76 | } 77 | else 78 | return move(map, currentState); 79 | } 80 | else if (map[currentState.y+y][currentState.x+x] == '#') 81 | return move(map, currentState); 82 | 83 | currentState.x += x; 84 | currentState.y += y; 85 | return directionToString(x, y); 86 | } 87 | 88 | int main() 89 | { 90 | std::vector> map; 91 | std::vector moves; 92 | std::vector> teleporters; 93 | State currentState; 94 | 95 | int L; 96 | int C; 97 | std::cin >> L >> C; std::cin.ignore(); 98 | for (int i = 0; i < L; i++) { 99 | std::string row; 100 | std::getline(std::cin, row); 101 | 102 | map.push_back({}); 103 | for (int j = 0; j < C; ++j) 104 | { 105 | map.back().push_back(row[j]); 106 | 107 | if (row[j] == '@') 108 | { 109 | currentState.x = j; 110 | currentState.y = i; 111 | } 112 | else if (row[j] == 'T') 113 | { 114 | teleporters.push_back({j, i}); 115 | } 116 | } 117 | } 118 | 119 | assert(teleporters.size() == 0 || teleporters.size() == 2); 120 | 121 | while (map[currentState.y][currentState.x] != '$') 122 | { 123 | // If we were already here that we are in an endless loop 124 | if (visited.find({currentState.x, currentState.y}) != visited.end()) 125 | { 126 | if (std::find(visited[{currentState.x, currentState.y}].begin(), 127 | visited[{currentState.x, currentState.y}].end(), 128 | currentState) != visited[{currentState.x, currentState.y}].end()) 129 | { 130 | std::cout << "LOOP" << std::endl; 131 | return 0; 132 | } 133 | } 134 | 135 | // Store the current state (to detect looping) 136 | visited[{currentState.x, currentState.y}].push_back(currentState); 137 | 138 | // Check if we have to do something special 139 | switch (map[currentState.y][currentState.x]) 140 | { 141 | case 'N': 142 | currentState.direction = "NORTH"; 143 | break; 144 | 145 | case 'E': 146 | currentState.direction = "EAST"; 147 | break; 148 | 149 | case 'S': 150 | currentState.direction = "SOUTH"; 151 | break; 152 | 153 | case 'W': 154 | currentState.direction = "WEST"; 155 | break; 156 | 157 | case 'I': 158 | currentState.inverted = !currentState.inverted; 159 | break; 160 | 161 | case 'B': 162 | currentState.breakerMode = !currentState.breakerMode; 163 | break; 164 | 165 | case 'T': 166 | { 167 | if ((currentState.x == teleporters[0].first) && (currentState.y == teleporters[0].second)) 168 | { 169 | currentState.x = teleporters[1].first; 170 | currentState.y = teleporters[1].second; 171 | } 172 | else 173 | { 174 | currentState.x = teleporters[0].first; 175 | currentState.y = teleporters[0].second; 176 | } 177 | break; 178 | } 179 | }; 180 | 181 | // Make our move 182 | if (currentState.direction == "NORTH") 183 | moves.push_back(makeMovement(0, -1, map, currentState)); 184 | else if (currentState.direction == "EAST") 185 | moves.push_back(makeMovement(1, 0, map, currentState)); 186 | else if (currentState.direction == "SOUTH") 187 | moves.push_back(makeMovement(0, 1, map, currentState)); 188 | else if (currentState.direction == "WEST") 189 | moves.push_back(makeMovement(-1, 0, map, currentState)); 190 | } 191 | 192 | for (std::string move : moves) 193 | std::cout << move << std::endl; 194 | 195 | return 0; 196 | } 197 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Thor VS Giants.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | pair findCenter(const vector>& giants) 10 | { 11 | int centerX = 0; 12 | int centerY = 0; 13 | for (auto& giant : giants) 14 | { 15 | centerX += giant.first; 16 | centerY += giant.second; 17 | } 18 | 19 | centerX /= giants.size(); 20 | centerY /= giants.size(); 21 | 22 | return {centerX, centerY}; 23 | } 24 | 25 | vector> findGiantsInRange(int TX, int TY, const vector>& giants) 26 | { 27 | vector> closeGiants; 28 | for (auto& giant : giants) 29 | { 30 | if ((abs(giant.first - TX) <= 4) && (abs(giant.second - TY) <= 4)) 31 | closeGiants.push_back(giant); 32 | } 33 | 34 | return closeGiants; 35 | } 36 | 37 | bool giantsTooClose(int TX, int TY, const vector>& giants) 38 | { 39 | for (auto& giant : giants) 40 | { 41 | if ((abs(giant.first - TX) <= 1) && (abs(giant.second - TY) <= 1)) 42 | return true; 43 | } 44 | 45 | return false; 46 | } 47 | 48 | string findMove(int& TX, int& TY, int CX, int CY) 49 | { 50 | if (CX > TX) 51 | { 52 | if (CY > TY) 53 | { 54 | TX += 1; 55 | TY += 1; 56 | return "SE"; 57 | } 58 | else if (CY < TY) 59 | { 60 | TX += 1; 61 | TY -= 1; 62 | return "NE"; 63 | } 64 | else 65 | { 66 | TX += 1; 67 | return "E"; 68 | } 69 | } 70 | else if (CX < TX) 71 | { 72 | if (CY > TY) 73 | { 74 | TX -= 1; 75 | TY += 1; 76 | return "SW"; 77 | } 78 | else if (CY < TY) 79 | { 80 | TX -= 1; 81 | TY -= 1; 82 | return "NW"; 83 | } 84 | else 85 | { 86 | TX -= 1; 87 | return "W"; 88 | } 89 | } 90 | else 91 | { 92 | if (CY > TY) 93 | { 94 | TY += 1; 95 | return "S"; 96 | } 97 | else if (CY < TY) 98 | { 99 | TY -= 1; 100 | return "N"; 101 | } 102 | else 103 | { 104 | return "WAIT"; 105 | } 106 | } 107 | } 108 | 109 | unsigned int dist(pair first, pair second) 110 | { 111 | return abs(first.first - second.first) + abs(first.second - second.second); 112 | } 113 | 114 | string findBestMove(int& TX, int& TY, const vector>& giants) 115 | { 116 | map>> profit; 117 | 118 | auto center = findCenter(giants); 119 | 120 | // Move towards the center of the enemies when no enemy standing next to you 121 | if (!giantsTooClose(TX, TY, giants)) 122 | return findMove(TX, TY, center.first, center.second); 123 | 124 | // Check in which direction we move best 125 | if (TX > 0) 126 | { 127 | int x = TX - 1; 128 | int y = TY; 129 | if (!giantsTooClose(x, y, giants)) 130 | profit["W"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 131 | } 132 | if (TY > 0) 133 | { 134 | int x = TX; 135 | int y = TY - 1; 136 | if (!giantsTooClose(x, y, giants)) 137 | profit["N"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 138 | } 139 | if (TX < 40) 140 | { 141 | int x = TX + 1; 142 | int y = TY; 143 | if (!giantsTooClose(x, y, giants)) 144 | profit["E"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 145 | } 146 | if (TY < 18) 147 | { 148 | int x = TX; 149 | int y = TY + 1; 150 | if (!giantsTooClose(x, y, giants)) 151 | profit["S"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 152 | } 153 | if ((TX > 0) && (TY > 0)) 154 | { 155 | int x = TX - 1; 156 | int y = TY - 1; 157 | if (!giantsTooClose(x, y, giants)) 158 | profit["NW"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 159 | } 160 | if ((TX < 40) && (TY > 0)) 161 | { 162 | int x = TX + 1; 163 | int y = TY - 1; 164 | if (!giantsTooClose(x, y, giants)) 165 | profit["NE"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 166 | } 167 | if ((TX > 0) && (TY > 0)) 168 | { 169 | int x = TX - 1; 170 | int y = TY - 1; 171 | if (!giantsTooClose(x, y, giants)) 172 | profit["SW"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 173 | } 174 | if ((TX < 40) && (TY < 18)) 175 | { 176 | int x = TX + 1; 177 | int y = TY + 1; 178 | if (!giantsTooClose(x, y, giants)) 179 | profit["SE"] = {findGiantsInRange(x, y, giants).size(), {x, y}}; 180 | } 181 | 182 | // Make the best move 183 | string move = "STRIKE"; 184 | pair> bestOption = {}; 185 | unsigned int bestDist = 0; 186 | for (auto& option : profit) 187 | { 188 | // Find the best option (move away from center when tie) 189 | if ((option.second.first > bestOption.first) || 190 | ((option.second.first == bestOption.first) && (dist(option.second.second, center) > bestDist))) 191 | { 192 | bestOption = option.second; 193 | move = option.first; 194 | bestDist = dist(bestOption.second, center); 195 | } 196 | } 197 | 198 | if (move != "STRIKE") 199 | { 200 | TX = bestOption.second.first; 201 | TY = bestOption.second.second; 202 | } 203 | 204 | return move; 205 | } 206 | 207 | int main() 208 | { 209 | int TX; 210 | int TY; 211 | cin >> TX >> TY; cin.ignore(); 212 | 213 | vector> giants; 214 | 215 | // game loop 216 | while (1) { 217 | giants.clear(); 218 | 219 | int H; // the remaining number of hammer strikes. 220 | int N; // the number of giants which are still present on the map. 221 | cin >> H >> N; cin.ignore(); 222 | for (int i = 0; i < N; i++) { 223 | int X; 224 | int Y; 225 | cin >> X >> Y; cin.ignore(); 226 | 227 | giants.push_back({X, Y}); 228 | } 229 | 230 | //auto center = findCenter(giants); 231 | vector> closeEnemies = findGiantsInRange(TX, TY, giants); 232 | 233 | // Once we can kill all giants, do so 234 | if (giants.size() == closeEnemies.size()) 235 | { 236 | cout << "STRIKE" << endl; 237 | continue; 238 | } 239 | 240 | int newTX = TX; 241 | int newTY = TY; 242 | string move = findBestMove(newTX, newTY, giants); 243 | 244 | cout << move << endl; 245 | TX = newTX; 246 | TY = newTY; 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /SingePlayer/Very Hard/Triangulation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int W; // width of the building. 9 | int H; // height of the building. 10 | vector> windows; 11 | 12 | int minX = 0; 13 | int minY = 0; 14 | int maxX; 15 | int maxY; 16 | 17 | double dist(pair point1, pair point2) 18 | { 19 | return sqrt(pow(point1.first - point2.first, 2) + pow(point1.second - point2.second, 2)); 20 | } 21 | 22 | // Centroid of set of points is calculated by: 23 | // ((x1,y1) + (x2,y2) + ... + (xk,yk)) / k 24 | // k is the amount of windows where the bomb might still be here 25 | pair calculateCentroid() 26 | { 27 | int k = 0; 28 | int totalX = 0; 29 | int totalY = 0; 30 | for (int h = minY; h < maxY; ++h) 31 | { 32 | for (int w = minX; w < maxX; ++w) 33 | { 34 | if (windows[h][w]) 35 | { 36 | k++; 37 | totalX += w; 38 | totalY += h; 39 | } 40 | } 41 | } 42 | 43 | return {int(round(totalX / (double)k)), int(round(totalY / (double)k))}; 44 | } 45 | 46 | int main() 47 | { 48 | cin >> W >> H; cin.ignore(); 49 | int N; // maximum number of turns before game over. 50 | cin >> N; cin.ignore(); 51 | int X0; 52 | int Y0; 53 | cin >> X0 >> Y0; cin.ignore(); 54 | 55 | windows = vector>(H, vector(W, true)); 56 | maxX = W; 57 | maxY = H; 58 | 59 | pair prevOldPosition{X0, Y0}; 60 | pair oldPosition{X0, Y0}; 61 | pair newPosition{X0, Y0}; 62 | 63 | // game loop 64 | bool centroid = false; 65 | while (1) { 66 | string BOMB_DIST; // Current distance to the bomb compared to previous distance (COLDER, WARMER, SAME or UNKNOWN) 67 | cin >> BOMB_DIST; cin.ignore(); 68 | 69 | // The normal calculations are only done up to 1000x1000 unexplored windows 70 | if ((maxX - minX) * (maxY - minY) <= 1000000) 71 | { 72 | // Mark windows where the bomb can no longer be 73 | if (BOMB_DIST == "WARMER") 74 | { 75 | for (int h = minY; h < maxY; ++h) 76 | { 77 | for (int w = minX; w < maxX; ++w) 78 | { 79 | if (windows[h][w] && dist(oldPosition, {w,h}) <= dist(newPosition, {w,h})) 80 | windows[h][w] = false; 81 | } 82 | } 83 | } 84 | else if (BOMB_DIST == "COLDER") 85 | { 86 | for (int h = minY; h < maxY; ++h) 87 | { 88 | for (int w = minX; w < maxX; ++w) 89 | { 90 | if (windows[h][w] && dist(oldPosition, {w,h}) >= dist(newPosition, {w,h})) 91 | windows[h][w] = false; 92 | } 93 | } 94 | } 95 | else if (BOMB_DIST == "SAME") 96 | { 97 | for (int h = minY; h < maxY; ++h) 98 | { 99 | for (int w = minX; w < maxX; ++w) 100 | { 101 | if (windows[h][w] && dist(oldPosition, {w,h}) != dist(newPosition, {w,h})) 102 | windows[h][w] = false; 103 | } 104 | } 105 | } 106 | 107 | // Jump to the centroid of the part where the bomb can still be 108 | prevOldPosition = oldPosition; 109 | oldPosition = newPosition; 110 | newPosition = calculateCentroid(); 111 | 112 | // Don't jump back or stand still, instead move one square in some direction 113 | if (newPosition == oldPosition || newPosition == prevOldPosition) 114 | { 115 | if (newPosition.first > 0 && windows[newPosition.second][newPosition.first-1]) 116 | newPosition.first--; 117 | else if (newPosition.second > 0 && windows[newPosition.second-1][newPosition.first]) 118 | newPosition.second--; 119 | else if (newPosition.second < H-1 && windows[newPosition.second+1][newPosition.first]) 120 | newPosition.second++; 121 | else if (newPosition.first < W-1 && windows[newPosition.second][newPosition.first+1]) 122 | newPosition.first++; 123 | else if (newPosition.first > 0 && newPosition.second > 0 && windows[newPosition.second-1][newPosition.first-1]) 124 | { 125 | newPosition.first--; 126 | newPosition.second--; 127 | } 128 | else if (newPosition.first > 0 && newPosition.second < H-1 && windows[newPosition.second+1][newPosition.first-1]) 129 | { 130 | newPosition.first--; 131 | newPosition.second++; 132 | } 133 | else if (newPosition.first < W-1 && newPosition.second > 0 && windows[newPosition.second-1][newPosition.first+1]) 134 | { 135 | newPosition.first++; 136 | newPosition.second--; 137 | } 138 | else if (newPosition.first < W-1 && newPosition.second < H-1 && windows[newPosition.second+1][newPosition.first+1]) 139 | { 140 | newPosition.first++; 141 | newPosition.second++; 142 | } 143 | } 144 | } 145 | else // There are too many windows for normal calculation 146 | { 147 | if (BOMB_DIST == "WARMER") 148 | { 149 | if (newPosition.first > oldPosition.first) 150 | minX = oldPosition.first + (newPosition.first - oldPosition.first); 151 | else if (newPosition.first < oldPosition.first) 152 | maxX = oldPosition.first - (oldPosition.first - newPosition.first); 153 | 154 | if (newPosition.second > oldPosition.second) 155 | minY = oldPosition.second + (newPosition.second - oldPosition.second); 156 | else if (newPosition.second < oldPosition.second) 157 | maxY = oldPosition.second - (oldPosition.second - newPosition.second); 158 | } 159 | else if (BOMB_DIST == "COLDER") 160 | { 161 | if (newPosition.first > oldPosition.first) 162 | maxX = newPosition.first - (newPosition.first - oldPosition.first); 163 | else if (newPosition.first < oldPosition.first) 164 | minX = newPosition.first + (oldPosition.first - newPosition.first); 165 | 166 | if (newPosition.second > oldPosition.second) 167 | maxY = newPosition.second - (newPosition.second - oldPosition.second); 168 | else if (newPosition.second < oldPosition.second) 169 | minY = newPosition.second + (oldPosition.second - newPosition.second); 170 | } 171 | 172 | prevOldPosition = oldPosition; 173 | oldPosition = newPosition; 174 | newPosition = {(maxX - minX) / 2, (maxY - minY) / 2}; 175 | } 176 | 177 | cout << newPosition.first << " " << newPosition.second << endl; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Skynet: The Bridge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | vector lanes(4); 9 | std::string::size_type lastHole; 10 | std::string::size_type trackLength; 11 | 12 | struct State 13 | { 14 | unsigned int speed; 15 | unsigned int x; 16 | vector y; 17 | }; 18 | 19 | // Returns casualties and best move 20 | pair decide(State state) 21 | { 22 | // Just keep going once you pass all holes 23 | if (state.x >= lastHole) 24 | return {0, "WAIT"}; 25 | 26 | // Don't just stand there, move! 27 | if (state.speed == 0) 28 | return {0, "SPEED"}; 29 | 30 | pair minCasualties = {state.y.size(), "WAIT"}; 31 | 32 | // Faster, go faster! This must be the default move to make it in time. 33 | { 34 | State newState = state; 35 | newState.speed += 1; 36 | newState.x += newState.speed; 37 | 38 | for (auto y : state.y) 39 | { 40 | for (unsigned int x = state.x + 1; x <= newState.x; ++x) 41 | { 42 | if (lanes[y][x] == '0') 43 | { 44 | newState.y.erase(std::find(newState.y.begin(), newState.y.end(), y)); 45 | break; 46 | } 47 | } 48 | } 49 | 50 | if (newState.y.size() > 0) 51 | { 52 | unsigned int casualties = (state.y.size() - newState.y.size()) + decide(newState).first; 53 | if (casualties == 0) 54 | return {0, "SPEED"}; 55 | 56 | if (casualties < minCasualties.first) 57 | minCasualties = {casualties, "SPEED"}; 58 | } 59 | } 60 | 61 | // Keep going 62 | { 63 | State newState = state; 64 | newState.x += newState.speed; 65 | 66 | for (auto y : state.y) 67 | { 68 | for (unsigned int x = state.x + 1; x <= newState.x; ++x) 69 | { 70 | if (lanes[y][x] == '0') 71 | { 72 | newState.y.erase(std::find(newState.y.begin(), newState.y.end(), y)); 73 | break; 74 | } 75 | } 76 | } 77 | 78 | if (newState.y.size() > 0) 79 | { 80 | unsigned int casualties = (state.y.size() - newState.y.size()) + decide(newState).first; 81 | if (casualties == 0) 82 | return {0, "WAIT"}; 83 | 84 | if (casualties < minCasualties.first) 85 | minCasualties = {casualties, "WAIT"}; 86 | } 87 | } 88 | 89 | // We lose at least one machine by just moving forward, so what about jumping? 90 | { 91 | State newState = state; 92 | newState.x += newState.speed; 93 | 94 | for (auto y : state.y) 95 | { 96 | if (lanes[y][newState.x] == '0') 97 | newState.y.erase(std::find(newState.y.begin(), newState.y.end(), y)); 98 | } 99 | 100 | if (newState.y.size() > 0) 101 | { 102 | unsigned int casualties = (state.y.size() - newState.y.size()) + decide(newState).first; 103 | if (casualties == 0) 104 | return {0, "JUMP"}; 105 | 106 | if (casualties < minCasualties.first) 107 | minCasualties = {casualties, "JUMP"}; 108 | } 109 | } 110 | 111 | // Try moving up 112 | if (std::find(state.y.begin(), state.y.end(), 0) == state.y.end()) 113 | { 114 | State newState = state; 115 | newState.x += newState.speed; 116 | newState.y = {}; 117 | 118 | for (auto y : state.y) 119 | { 120 | bool stillAlive = true; 121 | for (unsigned int x = state.x + 1; x <= newState.x - 1; ++x) 122 | { 123 | if (lanes[y][x] == '0') 124 | { 125 | stillAlive = false; 126 | break; 127 | } 128 | } 129 | for (unsigned int x = state.x + 1; x <= newState.x; ++x) 130 | { 131 | if (lanes[y-1][x] == '0') 132 | { 133 | stillAlive = false; 134 | break; 135 | } 136 | } 137 | 138 | if (stillAlive) 139 | newState.y.push_back(y - 1); 140 | } 141 | 142 | if (newState.y.size() > 0) 143 | { 144 | unsigned int casualties = (state.y.size() - newState.y.size()) + decide(newState).first; 145 | if (casualties == 0) 146 | return {0, "UP"}; 147 | 148 | if (casualties < minCasualties.first) 149 | minCasualties = {casualties, "UP"}; 150 | } 151 | } 152 | 153 | // Try moving down 154 | if (std::find(state.y.begin(), state.y.end(), lanes.size()-1) == state.y.end()) 155 | { 156 | State newState = state; 157 | newState.x += newState.speed; 158 | newState.y = {}; 159 | 160 | for (auto y : state.y) 161 | { 162 | bool stillAlive = true; 163 | for (unsigned int x = state.x + 1; x <= newState.x - 1; ++x) 164 | { 165 | if (lanes[y][x] == '0') 166 | { 167 | stillAlive = false; 168 | break; 169 | } 170 | } 171 | for (unsigned int x = state.x + 1; x <= newState.x; ++x) 172 | { 173 | if (lanes[y+1][x] == '0') 174 | { 175 | stillAlive = false; 176 | break; 177 | } 178 | } 179 | 180 | if (stillAlive) 181 | newState.y.push_back(y + 1); 182 | } 183 | 184 | if (newState.y.size() > 0) 185 | { 186 | unsigned int casualties = (state.y.size() - newState.y.size()) + decide(newState).first; 187 | if (casualties == 0) 188 | return {0, "DOWN"}; 189 | 190 | if (casualties < minCasualties.first) 191 | minCasualties = {casualties, "DOWN"}; 192 | } 193 | } 194 | 195 | // Slow down, will ya? 196 | if (state.speed > 1) 197 | { 198 | State newState = state; 199 | newState.speed -= 1; 200 | newState.x += newState.speed; 201 | 202 | for (auto y : state.y) 203 | { 204 | for (unsigned int x = state.x + 1; x <= newState.x; ++x) 205 | { 206 | if (lanes[y][x] == '0') 207 | { 208 | newState.y.erase(std::find(newState.y.begin(), newState.y.end(), y)); 209 | break; 210 | } 211 | } 212 | } 213 | 214 | if (newState.y.size() > 0) 215 | { 216 | unsigned int casualties = (state.y.size() - newState.y.size()) + decide(newState).first; 217 | if (casualties == 0) 218 | return {0, "SLOW"}; 219 | 220 | if (casualties < minCasualties.first) 221 | minCasualties = {casualties, "SLOW"}; 222 | } 223 | } 224 | 225 | // We can't all make it, choose a move that minimizes casualties 226 | return minCasualties; 227 | } 228 | 229 | int main() 230 | { 231 | int M; // the amount of motorbikes to control 232 | cin >> M; cin.ignore(); 233 | int V; // the minimum amount of motorbikes that must survive 234 | cin >> V; cin.ignore(); 235 | cin >> lanes[0]; cin.ignore(); 236 | cin >> lanes[1]; cin.ignore(); 237 | cin >> lanes[2]; cin.ignore(); 238 | cin >> lanes[3]; cin.ignore(); 239 | 240 | lastHole = 0; 241 | lastHole = max(lastHole, (lanes[0].rfind('0') != string::npos) ? lanes[0].rfind('0') : 0); 242 | lastHole = max(lastHole, (lanes[1].rfind('0') != string::npos) ? lanes[1].rfind('0') : 0); 243 | lastHole = max(lastHole, (lanes[2].rfind('0') != string::npos) ? lanes[2].rfind('0') : 0); 244 | lastHole = max(lastHole, (lanes[3].rfind('0') != string::npos) ? lanes[3].rfind('0') : 0); 245 | trackLength = lanes[0].length(); 246 | 247 | // game loop 248 | while (1) { 249 | int S; // the motorbikes' speed 250 | cin >> S; cin.ignore(); 251 | 252 | State currentState; 253 | currentState.speed = S; 254 | 255 | for (int i = 0; i < M; i++) { 256 | int X; // x coordinate of the motorbike 257 | int Y; // y coordinate of the motorbike 258 | int A; // indicates whether the motorbike is activated "1" or detroyed "0" 259 | cin >> X >> Y >> A; cin.ignore(); 260 | 261 | if (A) { 262 | currentState.x = X; 263 | currentState.y.push_back(Y); 264 | } 265 | } 266 | 267 | cout << decide(currentState).second << endl; 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Don't Panic - Episode 2.py: -------------------------------------------------------------------------------- 1 | import math 2 | import heapq 3 | 4 | # nb_floors: number of floors 5 | # width: width of the area 6 | # nb_rounds: maximum number of rounds 7 | # exit_floor: floor on which the exit is found 8 | # exit_pos: position of the exit on its floor 9 | # nb_total_clones: number of generated clones 10 | # nb_additional_elevators: number of additional elevators that you can build 11 | # nb_elevators: number of elevators 12 | nb_floors, width, nb_rounds, exit_floor, exit_pos, nb_total_clones, nb_additional_elevators, nb_elevators = [int(i) for i in input().split()] 13 | elevators = set() 14 | for i in range(nb_elevators): 15 | # elevator_floor: floor on which this elevator is found 16 | # elevator_pos: position of the elevator on its floor 17 | elevator_floor, elevator_pos = [int(j) for j in input().split()] 18 | elevators.add((elevator_floor, elevator_pos)) 19 | 20 | def calcHeuristicsMap(): 21 | # We create a 3-dimensional heuristics map. 22 | # Two dimensions are for the grid, and on dimension for the remaining elevators. 23 | # Each position thus has a different heuristic depending on how many elevators are yet to be placed. 24 | heuristics = [[[math.inf for z in range(nb_additional_elevators+1)] for x in range(width)] for y in range(nb_floors)] 25 | 26 | # The exit has a zero cost 27 | for i in range(nb_additional_elevators+1): 28 | heuristics[exit_floor][exit_pos][i] = 0 29 | 30 | # Calculate the heuristic cost to the exit by going down row by row 31 | for y in range(exit_floor, -1, -1): 32 | # Process every position on this row 33 | posToProcessInRow = set(range(0,width)) 34 | while posToProcessInRow: 35 | x = posToProcessInRow.pop() 36 | valueUpdated = False 37 | 38 | if (y,x) not in elevators: 39 | # Compare our cost with the left neightbor 40 | if x > 0: 41 | for z in range(nb_additional_elevators+1): 42 | if heuristics[y][x][z] > heuristics[y][x-1][z] + 1: 43 | heuristics[y][x][z] = heuristics[y][x-1][z] + 1 44 | valueUpdated = True 45 | 46 | # Compare our cost with the right neighbor 47 | if x+1 < width: 48 | for z in range(nb_additional_elevators+1): 49 | if heuristics[y][x][z] > heuristics[y][x+1][z] + 1: 50 | heuristics[y][x][z] = heuristics[y][x+1][z] + 1 51 | valueUpdated = True 52 | 53 | # Cost with more remaining elevators left to be placed can never be higher 54 | # than reaching the same position with less elevators left. 55 | for z in range(1, nb_additional_elevators+1): 56 | if heuristics[y][x][z] > heuristics[y][x][z-1]: 57 | heuristics[y][x][z] = heuristics[y][x][z-1] 58 | valueUpdated = True 59 | 60 | # If we updated our cost then we also need to recheck our neighbors 61 | if valueUpdated: 62 | if x > 0: 63 | posToProcessInRow.add(x-1) 64 | if x+1 < width: 65 | posToProcessInRow.add(x+1) 66 | 67 | # Now that we have processed the row, we will copy the value to the row 68 | # below it. All costs are increased by one, but if there is no elevator 69 | # then we copy our values to a different z value as we needed to build 70 | # an elevator on the row below us in order to make this transition. 71 | if y > 0: 72 | for x in range(width): 73 | if (y-1, x) in elevators: 74 | for z in range(nb_additional_elevators+1): 75 | heuristics[y-1][x][z] = heuristics[y][x][z] + 1 76 | else: 77 | for z in range(1, nb_additional_elevators+1): 78 | heuristics[y-1][x][z] = heuristics[y][x][z-1] + 1 79 | 80 | return heuristics 81 | 82 | 83 | def findShortestPath(cloneFloor, clonePos, initialMovingLeft, initialRemainingElevators): 84 | heuristics = calcHeuristicsMap() 85 | 86 | costs = [[[math.inf, math.inf] for x in range(width)] for y in range(nb_floors)] 87 | parents = {} 88 | 89 | statesToProcess = [] 90 | heapq.heappush(statesToProcess, (0, (cloneFloor, clonePos, initialMovingLeft, initialRemainingElevators))) 91 | 92 | while statesToProcess: 93 | cost, state = heapq.heappop(statesToProcess) 94 | floor, pos, movingLeft, nrRemainingElevators = state 95 | if floor == exit_floor and pos == exit_pos: 96 | reversedPath = [(floor, pos, movingLeft)] 97 | while reversedPath[-1] != (cloneFloor, clonePos, initialMovingLeft): 98 | reversedPath.append(parents[reversedPath[-1]]) 99 | return list(reversed(reversedPath)) 100 | 101 | posContainsElevator = (floor, pos) in elevators 102 | neighborStates = [] 103 | 104 | if pos > 0 and not posContainsElevator: 105 | if movingLeft: 106 | costLeft = heuristics[floor][pos-1][nrRemainingElevators] 107 | neighborStates.append((1, costLeft, floor, pos-1, True, nrRemainingElevators)) 108 | else: 109 | costSwitchDir = heuristics[floor][pos][nrRemainingElevators] 110 | neighborStates.append((3, costSwitchDir, floor, pos, True, nrRemainingElevators)) 111 | 112 | if pos+1 < width and not posContainsElevator: 113 | if movingLeft: 114 | costSwitchDir = heuristics[floor][pos][nrRemainingElevators] 115 | neighborStates.append((3, costSwitchDir, floor, pos, False, nrRemainingElevators)) 116 | else: 117 | costRight = heuristics[floor][pos+1][nrRemainingElevators] 118 | neighborStates.append((1, costRight, floor, pos+1, False, nrRemainingElevators)) 119 | 120 | if floor+1 < nb_floors: 121 | if posContainsElevator: 122 | costUp = heuristics[floor+1][pos][nrRemainingElevators] 123 | neighborStates.append((1, costUp, floor+1, pos, movingLeft, nrRemainingElevators)) 124 | elif nrRemainingElevators > 0: 125 | costUp = heuristics[floor+1][pos][nrRemainingElevators-1] 126 | neighborStates.append((1, costUp, floor+1, pos, movingLeft, nrRemainingElevators-1)) 127 | 128 | for neighborState in neighborStates: 129 | moveCost, heuristicCost, newFloor, newPos, newMovingLeft, newNrRemainingElevators = neighborState 130 | if cost == math.inf: 131 | continue 132 | 133 | newCost = cost + moveCost 134 | if (newFloor, newPos, newMovingLeft) not in parents or newCost + heuristicCost < costs[newFloor][newPos][newMovingLeft]: 135 | costs[newFloor][newPos][newMovingLeft] = newCost + heuristicCost 136 | parents[(newFloor, newPos, newMovingLeft)] = (floor, pos, movingLeft) 137 | heapq.heappush(statesToProcess, (newCost, (newFloor, newPos, newMovingLeft, newNrRemainingElevators))) 138 | 139 | # If we reach here then we didn't find a path. Which shouldn't be possible. 140 | assert(False) 141 | 142 | 143 | nrRemainingElevators = nb_additional_elevators 144 | blockedPositions = set() 145 | firstIteration = True 146 | pathToFollow = [] 147 | 148 | # game loop 149 | while True: 150 | inputs = input().split() 151 | clone_floor = int(inputs[0]) # floor of the leading clone 152 | clone_pos = int(inputs[1]) # position of the leading clone on its floor 153 | direction = inputs[2] # direction of the leading clone: LEFT or RIGHT 154 | 155 | if clone_floor == -1 and clone_pos == -1: 156 | print('WAIT') 157 | continue 158 | 159 | if clone_floor == exit_floor and clone_pos == exit_pos: 160 | print('WAIT') 161 | continue 162 | 163 | if (clone_floor, clone_pos) in elevators or (clone_floor, clone_pos) in blockedPositions: 164 | print('WAIT') 165 | continue 166 | 167 | # Calculate the entire path at the first iteration 168 | if firstIteration: 169 | pathToFollow = findShortestPath(clone_floor, clone_pos, direction == 'LEFT', nrRemainingElevators) 170 | firstIteration = False 171 | 172 | # Figure out where we are on the path and what our next step is 173 | idx = pathToFollow.index((clone_floor, clone_pos, direction == 'LEFT')) 174 | nextFloor, nextPos, movingLeft = pathToFollow[idx + 1] 175 | 176 | # Execute the next step in our planned path 177 | if nextFloor > clone_floor: 178 | print('ELEVATOR') 179 | elevators.add((clone_floor, clone_pos)) 180 | nrRemainingElevators -= 1 181 | elif (direction == 'LEFT') != movingLeft: 182 | print('BLOCK') 183 | blockedPositions.add((clone_floor, clone_pos)) 184 | else: 185 | print('WAIT') 186 | -------------------------------------------------------------------------------- /SingePlayer/Hard/There is no Spoon - Episode 2.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import copy 3 | from collections import defaultdict 4 | 5 | # Global variables that are initialized at the beginning 6 | nodes = [] 7 | conflictingEdges = defaultdict(list) 8 | 9 | # Global variables that contain the current state and are regularly changed 10 | nodeValues = {} 11 | edgeValues = {} 12 | lockedEdges = set() 13 | 14 | class Node: 15 | def __init__(self, x, y, number): 16 | self.x = x 17 | self.y = y 18 | self.number = number 19 | self.edges = [] 20 | 21 | class Edge: 22 | def __init__(self, node1, node2): 23 | self.node1 = node1 24 | self.node2 = node2 25 | edgeValues[self] = 0 26 | 27 | def isSolved(): 28 | for node in nodes: 29 | nrConnectedEdges = sum(edgeValues[edge] for edge in node.edges) 30 | if nrConnectedEdges != node.number: 31 | return False 32 | 33 | # Check that all nodes form a single connected group 34 | reachableNodes = set() 35 | reachableNodesToExamine = set() 36 | reachableNodesToExamine.add(nodes[0]) 37 | while reachableNodesToExamine: 38 | node = reachableNodesToExamine.pop() 39 | reachableNodes.add(node) 40 | for edge in node.edges: 41 | if edgeValues[edge] == 0: 42 | continue 43 | if edge.node1 not in reachableNodes: 44 | reachableNodesToExamine.add(edge.node1) 45 | if edge.node2 not in reachableNodes: 46 | reachableNodesToExamine.add(edge.node2) 47 | 48 | if len(reachableNodes) != len(nodes): 49 | return False 50 | 51 | return True 52 | 53 | def wouldBeOverlapping(edge): 54 | assert(edgeValues[edge] == 0) 55 | return any(edgeValues[otherEdge] > 0 for otherEdge in conflictingEdges[edge]) 56 | 57 | def getOtherNode(edge, node): 58 | assert(edge.node1 == node or edge.node2 == node) 59 | return edge.node2 if edge.node1 == node else edge.node1 60 | 61 | def getAvailableEdgesAtNode(node): 62 | return [edge for edge in node.edges \ 63 | if edge not in lockedEdges \ 64 | and ((edgeValues[edge] == 0 and not wouldBeOverlapping(edge)) \ 65 | or (edgeValues[edge] == 1 and nodeValues[getOtherNode(edge, node)] > 0))] 66 | 67 | def setEdgeValue(edge, value): 68 | assert(value > edgeValues[edge]) 69 | nodeValues[edge.node1] -= (value - edgeValues[edge]) 70 | nodeValues[edge.node2] -= (value - edgeValues[edge]) 71 | edgeValues[edge] = value 72 | return nodeValues[edge.node1] >= 0 and nodeValues[edge.node2] >= 0 73 | 74 | def markEdgeForReprocessing(edge, nodesToProcess): 75 | nodesToProcess.add(edge.node1) 76 | nodesToProcess.add(edge.node2) 77 | for conflictingEdge in conflictingEdges[edge]: 78 | nodesToProcess.add(conflictingEdge.node1) 79 | nodesToProcess.add(conflictingEdge.node2) 80 | 81 | def setGuaranteedEdges(addedEdge): 82 | if addedEdge: 83 | nodesToProcess = set() 84 | markEdgeForReprocessing(addedEdge, nodesToProcess) 85 | else: 86 | nodesToProcess = set(n for n in nodes) 87 | 88 | while nodesToProcess: 89 | node = nodesToProcess.pop() 90 | nrConnectedEdges = sum(edgeValues[edge] for edge in node.edges) 91 | 92 | # Skip if this node is already solved 93 | if nrConnectedEdges == node.number: 94 | continue 95 | 96 | availableEdges = getAvailableEdgesAtNode(node) 97 | 98 | # If there are no available edges left then we must have made a wrong decision earlier 99 | if not availableEdges: 100 | return False 101 | 102 | # If there is only one neighbor left then it must be connected with all available edges 103 | if len(availableEdges) == 1: 104 | remainingNodeNumber = nodeValues[node] 105 | if remainingNodeNumber != 1 and remainingNodeNumber != 2: 106 | # This is an invalid case, we must have made a wrong decision earlier 107 | return False 108 | 109 | edge = availableEdges[0] 110 | if edgeValues[edge] != remainingNodeNumber: 111 | if not setEdgeValue(edge, remainingNodeNumber): 112 | return False 113 | markEdgeForReprocessing(edge, nodesToProcess) 114 | continue 115 | 116 | # If all remaining sides can only be given 2 edges then we can do so 117 | if nodeValues[node] == 2 * len(availableEdges): 118 | for edge in availableEdges: 119 | if edgeValues[edge] != 2: 120 | if not setEdgeValue(edge, 2): 121 | return False 122 | markEdgeForReprocessing(edge, nodesToProcess) 123 | continue 124 | 125 | # If there is only one remaining option to distribute the edges then do so 126 | maxPossibleEdges = 0 127 | for edge in availableEdges: 128 | maxPossibleEdges += min(2, nodeValues[node], nodeValues[getOtherNode(edge, node)] + edgeValues[edge]) - edgeValues[edge] 129 | if maxPossibleEdges == nodeValues[node]: 130 | for edge in availableEdges: 131 | edgeValue = min(2, nodeValues[node], nodeValues[getOtherNode(edge, node)] + edgeValues[edge]) 132 | if edgeValue == 0: 133 | continue 134 | if not setEdgeValue(edge, edgeValue): 135 | return False 136 | markEdgeForReprocessing(edge, nodesToProcess) 137 | continue 138 | 139 | return True 140 | 141 | def attemptEdge(): 142 | global nodeValues 143 | global edgeValues 144 | 145 | reachableNodes = set() 146 | reachableNodesToExamine = set() 147 | reachableNodesToExamine.add(nodes[0]) 148 | while reachableNodesToExamine: 149 | node = reachableNodesToExamine.pop() 150 | reachableNodes.add(node) 151 | for edge in node.edges: 152 | if edgeValues[edge] == 0: 153 | continue 154 | if edge.node1 not in reachableNodes: 155 | reachableNodesToExamine.add(edge.node1) 156 | if edge.node2 not in reachableNodes: 157 | reachableNodesToExamine.add(edge.node2) 158 | 159 | for node in reachableNodes: 160 | availableEdges = getAvailableEdgesAtNode(node) 161 | for edge in availableEdges: 162 | if edgeValues[edge] == 0 and wouldBeOverlapping(edge): 163 | continue 164 | minEdges = edgeValues[edge] + 1 165 | maxEdges = 2 - edgeValues[edge] 166 | for i in range(maxEdges, minEdges-1, -1): 167 | assert(i == 1 or i == 2) 168 | if nodeValues[edge.node1] < i or nodeValues[edge.node2] < i: 169 | continue 170 | if edge.node1.number == i and edge.node2.number == i: # Don't connect two '2' nodes with two edges 171 | continue 172 | 173 | oldNodeValues = copy.copy(nodeValues) 174 | oldEdgeValues = copy.copy(edgeValues) 175 | lockedEdges.add(edge) 176 | 177 | if setEdgeValue(edge, i): 178 | setGuaranteedEdges(edge) 179 | if isSolved() or attemptEdge(): 180 | return True 181 | 182 | lockedEdges.remove(edge) 183 | nodeValues = oldNodeValues 184 | edgeValues = oldEdgeValues 185 | 186 | 187 | # We tried all remaining options and couldn't find a working one, we need to backtrack 188 | return False 189 | 190 | 191 | nodeByPos = {} 192 | 193 | width = int(input()) # the number of cells on the X axis 194 | height = int(input()) # the number of cells on the Y axis 195 | for i in range(height): 196 | line = input() # width characters, each either a number or a '.' 197 | for j in range(len(line)): 198 | if line[j] != '.': 199 | node = Node(j, i, int(line[j])) 200 | nodes.append(node) 201 | nodeByPos[(j,i)] = node 202 | nodeValues[node] = int(line[j]) 203 | 204 | for node1 in nodes: 205 | for x in range(node1.x + 1, width): 206 | if (x, node1.y) in nodeByPos: 207 | node2 = nodeByPos[(x, node1.y)] 208 | edge = Edge(node1, node2) 209 | node1.edges.append(edge) 210 | node2.edges.append(edge) 211 | break 212 | for y in range(node1.y + 1, height): 213 | if (node1.x, y) in nodeByPos: 214 | node2 = nodeByPos[(node1.x, y)] 215 | edge = Edge(node1, node2) 216 | node1.edges.append(edge) 217 | node2.edges.append(edge) 218 | break 219 | 220 | for edge1 in edgeValues: 221 | for edge2 in edgeValues: 222 | if edge1.node1.x == edge1.node2.x and edge2.node1.y == edge2.node2.y: 223 | if min(edge2.node1.x, edge2.node2.x) < edge1.node1.x and max(edge2.node1.x, edge2.node2.x) > edge1.node1.x \ 224 | and min(edge1.node1.y, edge1.node2.y) < edge2.node1.y and max(edge1.node1.y, edge1.node2.y) > edge2.node1.y: 225 | conflictingEdges[edge1].append(edge2) 226 | if edge1.node1.y == edge1.node2.y and edge2.node1.x == edge2.node2.x: 227 | if min(edge1.node1.x, edge1.node2.x) < edge2.node1.x and max(edge1.node1.x, edge1.node2.x) > edge2.node1.x \ 228 | and min(edge2.node1.y, edge2.node2.y) < edge1.node1.y and max(edge2.node1.y, edge2.node2.y) > edge1.node1.y: 229 | conflictingEdges[edge1].append(edge2) 230 | 231 | setGuaranteedEdges(None) 232 | if not isSolved(): 233 | attemptEdge() 234 | 235 | allEdges = set() 236 | for node in nodes: 237 | allEdges.update(node.edges) 238 | 239 | for edge in allEdges: 240 | if edgeValues[edge] > 0: 241 | print(edge.node1.x, edge.node1.y, edge.node2.x, edge.node2.y, edgeValues[edge]) 242 | -------------------------------------------------------------------------------- /SingePlayer/Hard/Winamax Sponsored Contest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | struct Pos 10 | { 11 | unsigned int x; 12 | unsigned int y; 13 | 14 | bool operator==(const Pos& other) const 15 | { 16 | return (x == other.x) && (y == other.y); 17 | } 18 | }; 19 | 20 | struct Ball 21 | { 22 | Pos pos; 23 | unsigned int count; 24 | }; 25 | 26 | using BallTrajectory = std::vector; 27 | using BallTrajectoryOptions = std::vector; 28 | 29 | std::vector> inputGrid; 30 | std::vector> outputGrid; 31 | 32 | // Checks if the ball flies over a hole, which is not allowed 33 | bool ballCrossesHole(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) 34 | { 35 | if (y1 == y2) 36 | { 37 | for (unsigned int x = x1 + 1; x < x2; ++x) 38 | { 39 | if (inputGrid[x][y1] == 'H') 40 | return true; 41 | } 42 | } 43 | else // if (x1 == x2) 44 | { 45 | for (unsigned int y = y1 + 1; y < y2; ++y) 46 | { 47 | if (inputGrid[x1][y] == 'H') 48 | return true; 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | 55 | // For a given ball, this function calculates all possible next positions recursively. 56 | // Each trajectory contains a list of positions where the ball stops before ending in 57 | // a hole. The trajectory is stored backwards (hole location is first in list) so that 58 | // the recursive code can push positions at the back of the vector instead of the front. 59 | BallTrajectoryOptions calculatePossibleBallTrajectories(Ball ball) 60 | { 61 | // There are up to 4 positions where the ball could land after hitting it 62 | std::vector ballOptions; 63 | if ((ball.pos.x >= ball.count) 64 | && (inputGrid[ball.pos.x - ball.count][ball.pos.y] != 'X') 65 | && !ballCrossesHole(ball.pos.x - ball.count, ball.pos.y, ball.pos.x, ball.pos.y)) 66 | { 67 | ballOptions.push_back({{ball.pos.x - ball.count, ball.pos.y}, ball.count-1}); 68 | } 69 | if ((ball.pos.x + ball.count < inputGrid.size()) 70 | && (inputGrid[ball.pos.x + ball.count][ball.pos.y] != 'X') 71 | && !ballCrossesHole(ball.pos.x, ball.pos.y, ball.pos.x + ball.count, ball.pos.y)) 72 | { 73 | ballOptions.push_back({{ball.pos.x + ball.count, ball.pos.y}, ball.count-1}); 74 | } 75 | if ((ball.pos.y >= ball.count) 76 | && (inputGrid[ball.pos.x][ball.pos.y - ball.count] != 'X') 77 | && !ballCrossesHole(ball.pos.x, ball.pos.y - ball.count, ball.pos.x, ball.pos.y)) 78 | { 79 | ballOptions.push_back({{ball.pos.x, ball.pos.y - ball.count}, ball.count-1}); 80 | } 81 | if ((ball.pos.y + ball.count < inputGrid[0].size()) 82 | && (inputGrid[ball.pos.x][ball.pos.y + ball.count] != 'X') 83 | && !ballCrossesHole(ball.pos.x, ball.pos.y, ball.pos.x, ball.pos.y + ball.count)) 84 | { 85 | ballOptions.push_back({{ball.pos.x, ball.pos.y + ball.count}, ball.count-1}); 86 | } 87 | 88 | // For each of those 4 positions, recursively calculate the next positions 89 | BallTrajectoryOptions steps; 90 | for (Ball& nextBall : ballOptions) 91 | { 92 | if (inputGrid[nextBall.pos.x][nextBall.pos.y] == 'H') 93 | steps.push_back(BallTrajectory(1, nextBall.pos)); 94 | else if (nextBall.count > 0) 95 | { 96 | auto nextSteps = calculatePossibleBallTrajectories(nextBall); 97 | for (auto& step : nextSteps) 98 | steps.push_back(std::move(step)); 99 | } 100 | } 101 | 102 | // Add the current ball position to the trajectories 103 | for (auto& step : steps) 104 | step.push_back(ball.pos); 105 | 106 | return steps; 107 | } 108 | 109 | // Changes part of a row or column in the output grid. 110 | // Unless the contents of the line is being removed, this function will first 111 | // check that all cells on the line are still empty and return false otherwise. 112 | bool changeLine(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, char value) 113 | { 114 | bool erasing = (value == '.'); 115 | 116 | if (y1 == y2) 117 | { 118 | for (unsigned int x = x1; x <= x2; ++x) 119 | { 120 | if (!erasing && (outputGrid[x][y1] != '.')) 121 | return false; 122 | } 123 | 124 | for (unsigned int x = x1; x <= x2; ++x) 125 | outputGrid[x][y1] = value; 126 | } 127 | else // if (x1 == x2) 128 | { 129 | for (unsigned int y = y1; y <= y2; ++y) 130 | { 131 | if (!erasing && (outputGrid[x1][y] != '.')) 132 | return false; 133 | } 134 | 135 | for (unsigned int y = y1; y <= y2; ++y) 136 | outputGrid[x1][y] = value; 137 | } 138 | 139 | return true; 140 | } 141 | 142 | // Try all combinations recursively and backtrack when stuck 143 | bool findSolutionTrajectories(const std::vector& combinations, std::vector& usedHoles, unsigned int ballIndex) 144 | { 145 | for (unsigned int index = 0; index < combinations[ballIndex].size(); ++index) 146 | { 147 | const auto& trajectory = combinations[ballIndex][index]; 148 | 149 | // If the trajectory ends in a hole that is already filled by another ball then we can 150 | // skip it entirely without having to do further calculations 151 | if (std::find(usedHoles.begin(), usedHoles.end(), trajectory.back()) != usedHoles.end()) 152 | continue; 153 | 154 | bool valid = true; 155 | unsigned int trajectoryIndex; 156 | for (trajectoryIndex = 1; trajectoryIndex < trajectory.size(); ++trajectoryIndex) 157 | { 158 | const Pos& currentPos = trajectory[trajectoryIndex - 1]; 159 | const Pos& nextPos = trajectory[trajectoryIndex]; 160 | if (currentPos.x < nextPos.x) 161 | valid = changeLine(currentPos.x, currentPos.y, nextPos.x - 1, nextPos.y, '>'); 162 | else if (currentPos.x > nextPos.x) 163 | valid = changeLine(nextPos.x + 1, nextPos.y, currentPos.x, currentPos.y, '<'); 164 | else if (currentPos.y < nextPos.y) 165 | valid = changeLine(currentPos.x, currentPos.y, nextPos.x, nextPos.y - 1, 'v'); 166 | else if (currentPos.y > nextPos.y) 167 | valid = changeLine(nextPos.x, nextPos.y + 1, currentPos.x, currentPos.y, '^'); 168 | 169 | if (!valid) 170 | break; 171 | } 172 | 173 | // If there is no overlap with previous balls then proceed with testing the other balls 174 | if (valid && (ballIndex + 1 < combinations.size())) 175 | { 176 | usedHoles.push_back(trajectory.back()); 177 | if (!findSolutionTrajectories(combinations, usedHoles, ballIndex + 1)) 178 | { 179 | // If there is valid trajectory for the other balls then we still need to change 180 | // the trajectory for this ball. 181 | usedHoles.pop_back(); 182 | valid = false; 183 | } 184 | } 185 | 186 | if (valid) 187 | { 188 | // We found the solution 189 | return true; 190 | } 191 | else // The trajectory overlapped, so undo the markings on the grid 192 | { 193 | for (trajectoryIndex = trajectoryIndex - 1; trajectoryIndex > 0; --trajectoryIndex) 194 | { 195 | const Pos& prevPos = trajectory[trajectoryIndex - 1]; 196 | const Pos& currentPos = trajectory[trajectoryIndex]; 197 | if (prevPos.x < currentPos.x) 198 | changeLine(prevPos.x, prevPos.y, currentPos.x - 1, currentPos.y, '.'); 199 | else if (prevPos.x > currentPos.x) 200 | changeLine(currentPos.x + 1, currentPos.y, prevPos.x, prevPos.y, '.'); 201 | else if (prevPos.y < currentPos.y) 202 | changeLine(prevPos.x, prevPos.y, currentPos.x, currentPos.y - 1, '.'); 203 | else if (prevPos.y > currentPos.y) 204 | changeLine(currentPos.x, currentPos.y + 1, prevPos.x, prevPos.y, '.'); 205 | } 206 | } 207 | } 208 | 209 | // None of the trajectories is valid for this ball, another ball must change his trajectory 210 | return false; 211 | } 212 | 213 | int main() 214 | { 215 | std::vector balls; 216 | 217 | unsigned int width; 218 | unsigned int height; 219 | cin >> width >> height; cin.ignore(); 220 | inputGrid.resize(width, std::vector(height)); 221 | for (unsigned int y = 0; y < height; y++) { 222 | string row; 223 | cin >> row; cin.ignore(); 224 | for (unsigned int x = 0; x < width; ++x) 225 | { 226 | inputGrid[x][y] = row[x]; 227 | if ((row[x] >= '1') && (row[x] <= '9')) 228 | balls.push_back({{x, y}, row[x]-'0'}); 229 | } 230 | } 231 | 232 | // First we calculate all valid trajectories for all balls while ignoring 233 | // the existence of the other balls. 234 | std::vector allBallTrajectories; 235 | for (const auto& ball : balls) 236 | allBallTrajectories.push_back(calculatePossibleBallTrajectories(ball)); 237 | 238 | // The trajectories were created in reverse order, so reverse them here to have 239 | // the current step in front and the final step in the back. 240 | for (auto& trajectoryOptions : allBallTrajectories) 241 | { 242 | for (auto& trajectory : trajectoryOptions) 243 | std::reverse(trajectory.begin(), trajectory.end()); 244 | } 245 | 246 | // For the found trajectories, we now have to find the one for each ball which 247 | // doesn't overlap with any other ball trajectory 248 | outputGrid = std::vector>(inputGrid.size(), std::vector(inputGrid[0].size(), '.')); 249 | std::vector usedHoles; 250 | findSolutionTrajectories(allBallTrajectories, usedHoles, 0); 251 | 252 | // Finally print the result 253 | for (unsigned int y = 0; y < height; y++) 254 | { 255 | std::string row; 256 | for (unsigned int x = 0; x < width; ++x) 257 | row.push_back(outputGrid[x][y]); 258 | 259 | std::cout << row << std::endl; 260 | } 261 | } 262 | --------------------------------------------------------------------------------