├── D1L1 ├── AfraidOfEven.cpp ├── AgeEncoding.cpp ├── AllButOneDivisor.cpp ├── BadNeighbors.cpp ├── BallRemoval.cpp ├── BallsSeparating.cpp ├── BinaryCards.cpp ├── BlackWhiteMagic.cpp ├── BoxUnion.cpp ├── BuildBridge.cpp ├── ChangingSounds.cpp ├── ChessMetric.cpp ├── CombinationLock.cpp ├── DateFormat.cpp ├── DateFormat.hs ├── DateFormat.java ├── DigitPrime.cpp ├── DropCoins.cpp ├── DropCoins.hs ├── GeneralChess.cpp ├── GirlsAndBoys.cpp ├── HouseBuilding.cpp ├── IPConverter.cpp ├── InterestingDigits.cpp ├── IsomorphicWords.cpp ├── LameKnight.cpp ├── LameKnight.hs ├── LameKnight.java ├── LuckyRemainder.cpp ├── LuckyRemainder.hs ├── LuckyRemainder.java ├── MinimumLiars.cpp ├── MissingParentheses.cpp ├── MissingParentheses.hs ├── NextNumber.cpp ├── OneFight.cpp ├── OrderedNim.cpp ├── OrthogonalAnagram.cpp ├── PerfectPermutation.cpp ├── PeriodicJumping.hs ├── RedSquare.cpp ├── RoadConstruction.cpp ├── SlimeXSlimesCity.cpp ├── SlimeXSlimesCity.hs ├── SlimeXSlimesCity.java ├── Spamatronic.cpp ├── Spamatronic.hs ├── Spamatronic.java ├── SpiralNumbers.cpp ├── StrongPrimePower.cpp ├── StrongPrimePower.hs ├── StrongPrimePower.java ├── TallPeople.cpp ├── TheSquareRootDilemma.cpp ├── ThirtyOne.cpp ├── Underprimes.cpp ├── WindowManager.cpp ├── WordCompositionGame.cpp └── ZigZag.cpp ├── D1L2 ├── BombMan.cpp ├── CoinMachinesGame.cpp ├── DungeonEscape.cpp ├── FlowerGarden.cpp ├── GameEnding.cpp ├── Jewelry.cpp ├── JimmyLightning.cpp ├── KeysInBoxes.cpp ├── OddsAndEvens.cpp ├── Paths.cpp ├── ReversalChain.cpp ├── Rumor.cpp └── StripePainter.cpp ├── D1L3 ├── IslandFerries.cpp ├── KiloManX.cpp ├── RoboCourier.cpp └── RookAttack.cpp ├── D2L1 ├── Archery.cpp ├── BishopMove.go ├── BishopMove.py ├── BlackAndWhiteSolitaire.cpp ├── Chopsticks.cpp ├── ClockWalk.cpp ├── DietPlan.cpp ├── DigitHoles.cpp ├── DigitHoles.hs ├── DigitHoles.java ├── DinkyFish.cpp ├── DitherCounter.cpp ├── EasyHomework.cpp ├── FilipTheFrog.js ├── GardenHose.cpp ├── IncredibleMachineEasy.cpp ├── IncredibleMachineEasy.hs ├── IncredibleMachineEasy.java ├── InfiniteString.rb ├── MostCommonLetters.cpp ├── NinjaTurtles.cpp ├── OnLineRank.cpp ├── PaperRockScisQuals.cpp ├── RainyRoad.cpp ├── RainyRoad.hs ├── RedAndGreen.cpp ├── RedAndGreen.hs ├── Reppity.cpp ├── SRMCards.cpp ├── SRMCards.hs ├── SRMCards.java ├── SRMRoomAssignmentPhase.cpp ├── SRMRoomAssignmentPhase.hs ├── Segments.cpp ├── SerialNumbers.cpp ├── SnowyWinter.cpp ├── Target.hs ├── TeamsSelection.cpp ├── TrainingCamp.cpp ├── TrainingCamp.hs ├── TrainingCamp.java ├── UnluckyNumbers.cpp └── WidgetRepairs.cpp ├── D2L2 ├── AlternateColors.cpp ├── CasketOfStarEasy.cpp ├── CoinsGameEasy.cpp ├── GravityBomb.cpp ├── GravityBomb.hs ├── GravityBomb.java ├── Jumping.hs ├── MovieSeating.cpp ├── MovieSeating.hs ├── MovieSeating.java ├── PseudoPrimeTest.cpp └── ThreeTeleports.cpp ├── D2L3 ├── BestApproximationDiv2.cpp ├── BestApproximationDiv2.hs ├── BestApproximationDiv2.java ├── ComplexIntegers.cpp ├── DiskScheduler.cpp ├── DivisibleSequence.cpp ├── EngineersPrimes.cpp ├── KthElement.cpp ├── LightedPanels.cpp ├── MagicalGirl.cpp ├── MagicalSquare.cpp ├── MarbleCollectionGame.cpp ├── MirrorPath.cpp ├── QuickSums.cpp ├── ShortPalindromes.cpp └── TopView.cpp └── README.md /D1L1/AfraidOfEven.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | bool attempt(vector &b) { 5 | int d = b[1] - b[0]; 6 | for (int i = 2; i < b.size(); ++i) { 7 | int x = b[i - 1] + d, y = x; 8 | while (x % 2 == 0) { 9 | x /= 2; 10 | } 11 | if (x != b[i]) { 12 | return false; 13 | } 14 | b[i] = y; 15 | } 16 | return true; 17 | } 18 | 19 | vector restoreProgression(vector const &a) { 20 | for (int x = a[0]; ; x *= 2) { 21 | for (int y = a[1]; y <= 1000 || y < x; y *= 2) { 22 | vector b(a); b[0] = x; b[1] = y; 23 | if (attempt(b)) { 24 | return b; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /D1L1/AgeEncoding.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | double const MARGIN = 1e-9; 8 | 9 | int convert(char c) { 10 | return c == '0' ? 0 : 1; 11 | } 12 | 13 | double compute(double base, vector const &a) { 14 | double ret = 0, x = 1; 15 | for (int i = a.size() - 1; i >= 0; --i) { 16 | ret += x * a[i]; 17 | x *= base; 18 | } 19 | return ret; 20 | } 21 | 22 | double binary(double age, vector const &a, double lo, double hi) { 23 | double base = (lo + hi)/2; 24 | double temp = compute(base, a); 25 | double diff = temp - age; 26 | if (abs(diff) < MARGIN) { 27 | return base; 28 | } else if (diff > 0) { 29 | return binary(age, a, lo, base); 30 | } else { 31 | return binary(age, a, base, hi); 32 | } 33 | } 34 | 35 | double getRadix(int age, string const &candlesLine) { 36 | vector a(candlesLine.size()); 37 | transform(begin(candlesLine), end(candlesLine), begin(a), convert); 38 | int sum = accumulate(begin(a), end(a), 0); 39 | if (sum == 0) { 40 | return -1; 41 | } else if (a[a.size() - 1] == 1) { 42 | if (sum == 1) { 43 | return age == 1 ? -2 : -1; 44 | } else if (age == 1) { 45 | return -1; 46 | } 47 | } 48 | return binary((double) age, a, 0, 100); 49 | } 50 | -------------------------------------------------------------------------------- /D1L1/AllButOneDivisor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int MAX_INT = 1 << 30; 7 | 8 | int gcd(int p, int q) { 9 | if (q == 0) { 10 | return p; 11 | } 12 | return gcd(q, p % q); 13 | } 14 | 15 | int lcm(int p, int q) { 16 | return (p * q) / gcd(p, q); 17 | } 18 | 19 | int getMinimum(vector a) { 20 | int n = a.size(), ret = MAX_INT; 21 | for (int k = 0; k != n; ++k) { 22 | int x = 1; 23 | for (int i = 0; i != n; ++i) { 24 | if (i != k) { 25 | x = lcm(x, a[i]); 26 | } 27 | } 28 | if (x % a[k] != 0) { 29 | ret = min(ret, x); 30 | } 31 | } 32 | return ret == MAX_INT ? -1 : ret; 33 | } 34 | -------------------------------------------------------------------------------- /D1L1/BadNeighbors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int linear(vector const &a, int lo, int hi) { 6 | if (lo == hi) { 7 | return a[lo]; 8 | } 9 | int dp[40]; 10 | dp[lo] = a[lo]; dp[lo + 1] = max(a[lo], a[lo + 1]); 11 | for (int i = lo + 2; i <= hi; ++i) { 12 | dp[i] = max(dp[i - 1], dp[i - 2] + a[i]); 13 | } 14 | return dp[hi]; 15 | } 16 | 17 | int circular(vector const &a) { 18 | int n = a.size(); 19 | return max(linear(a, 0, n - 2), linear(a, 1, n - 1)); 20 | } 21 | 22 | int maxDonations(vector const &a) { 23 | return circular(a); 24 | } 25 | -------------------------------------------------------------------------------- /D1L1/BallRemoval.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | bool memo[50][50]; 8 | bool done[50][50]; 9 | int n; 10 | string a; 11 | 12 | // Can the substring from l to r (inclusive) be removed entirely by itself? 13 | bool canRemove(int l, int r) { 14 | if (l > r) { 15 | return true; 16 | } 17 | if (l == r) { 18 | return false; 19 | } 20 | if (done[l][r]) { 21 | return memo[l][r]; 22 | } 23 | 24 | bool ret = false; 25 | 26 | // Try selecting the last chosen ball such that this ball will remove the entire substring 27 | for (int last = max(l, 1); last <= min(r, n - 2); ++last) { 28 | if (a[last] == '<') { 29 | if (!canRemove(last + 1, r)) { 30 | continue; 31 | } 32 | for (int i = l; i < last; ++i) { 33 | if (canRemove(l, i - 1) && canRemove(i + 1, last - 1)) { 34 | ret = true; 35 | goto finally; 36 | } 37 | } 38 | } else { 39 | if (!canRemove(l, last - 1)) { 40 | continue; 41 | } 42 | for (int i = last + 1; i <= r; ++i) { 43 | if (canRemove(last + 1, i - 1) && canRemove(i + 1, r)) { 44 | ret = true; 45 | goto finally; 46 | } 47 | } 48 | } 49 | } 50 | 51 | finally: 52 | done[l][r] = true; 53 | memo[l][r] = ret; 54 | return ret; 55 | } 56 | 57 | string canLeave(string const &label) { 58 | a = label; n = a.size(); 59 | memset(done, false, sizeof done); 60 | 61 | ostringstream ret; 62 | for (int i = 0; i < n; ++i) { 63 | if (canRemove(0, i - 1) && canRemove(i + 1, n - 1)) { 64 | ret << 'o'; 65 | } else { 66 | ret << '.'; 67 | } 68 | } 69 | 70 | return ret.str(); 71 | } 72 | -------------------------------------------------------------------------------- /D1L1/BallsSeparating.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int minOperations(vector const &red, 6 | vector const &green, 7 | vector const &blue) { 8 | int n = red.size(); 9 | if (n < 3) { 10 | return -1; 11 | } 12 | int ret = 150000000; 13 | for (int r = 0; r < n; ++r) { 14 | for (int g = 0; g < n; ++g) { 15 | for (int b = 0; b < n; ++b) { 16 | if (r == g || b == r || b == g) { 17 | continue; 18 | } 19 | int temp = green[r] + blue[r] + 20 | red[g] + blue[g] + 21 | red[b] + green[b]; 22 | for (int i = 0; i < n; ++i) { 23 | if (i == r || i == g || i == b) { 24 | continue; 25 | } 26 | temp += red[i] + green[i] + blue[i] - 27 | max(red[i], max(green[i], blue[i])); 28 | } 29 | ret = min(ret, temp); 30 | } 31 | } 32 | } 33 | return ret; 34 | } 35 | -------------------------------------------------------------------------------- /D1L1/BinaryCards.cpp: -------------------------------------------------------------------------------- 1 | // The code below implements my approach. 2 | // It's not too elegant but it's quite simple to observe. 3 | // For optimal solution: http://apps.topcoder.com/wiki/display/tc/SRM+519 4 | 5 | int64 largestNumber(int64 x, int64 y) { 6 | if (y < 2) { 7 | return y; 8 | } 9 | int64 mid = 1; 10 | for (int64 temp = y; temp > 1; temp >>= 1) { 11 | mid <<= 1; 12 | } 13 | if (mid > x) { 14 | return (mid << 1) - 1; 15 | } 16 | return mid + largestNumber(x - mid, y - mid); 17 | } 18 | -------------------------------------------------------------------------------- /D1L1/BlackWhiteMagic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int count(string const &a) { 6 | int w = 0, n = a .size(), ret = 0; 7 | for (int i = 0; i != n; ++i) { 8 | if (a[i] == 'W') { 9 | ++w; 10 | } 11 | } 12 | for (int i = w; i != n; ++i) { 13 | if (a[i] == 'W') { 14 | ++ret; 15 | } 16 | } 17 | return ret; 18 | } 19 | -------------------------------------------------------------------------------- /D1L1/BoxUnion.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct Rec { 8 | int x1, y1, x2, y2; 9 | 10 | static Rec read(string const &s) { 11 | istringstream iss(s); 12 | int x1, y1, x2, y2; 13 | iss >> x1 >> y1 >> x2 >> y2; 14 | Rec ret = {x1, y1, x2, y2}; 15 | return ret; 16 | } 17 | 18 | int area() const { 19 | return max(x2 - x1, 0) * max(y2 - y1, 0); 20 | } 21 | 22 | Rec intersect(Rec const& that) const { 23 | Rec ret = { max(x1, that.x1), max(y1, that.y1) 24 | , min(x2, that.x2), min(y2, that.y2) }; 25 | return ret; 26 | } 27 | }; 28 | 29 | int area(vector const &recs) { 30 | vector a(recs.size()); 31 | transform(begin(recs), end(recs), begin(a), Rec::read); 32 | 33 | if (a.size() == 1) { 34 | return a[0].area(); 35 | } 36 | 37 | Rec x = a[0].intersect(a[1]); 38 | if (a.size() == 2) { 39 | return a[0].area() + a[1].area() - x.area(); 40 | } 41 | 42 | Rec y = a[1].intersect(a[2]), 43 | z = a[2].intersect(a[0]), 44 | xyz = x.intersect(a[2]); 45 | return a[0].area() + a[1].area() + a[2].area() - 46 | (x.area() + y.area() + z.area()) + xyz.area(); 47 | } 48 | -------------------------------------------------------------------------------- /D1L1/BuildBridge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int howManyCards(int D, int L) { 6 | double x = 0; 7 | double y = 2.0*D/L; 8 | for (int i = 1; ; ++i) { 9 | x += 1.0 / i; 10 | if (x >= y) { 11 | return i; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /D1L1/ChangingSounds.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int maxFinal(vector const &a, int start, int limit) { 6 | int n = a.size(); 7 | 8 | bool b[n + 1][limit + 1]; 9 | memset(b, false, sizeof(b)); 10 | 11 | b[0][start] = true; 12 | for (int i = 0; i != n; ++i) { 13 | for (int j = 0; j <= limit; ++j) { 14 | if (b[i][j]) { 15 | if (j >= a[i]) { 16 | b[i + 1][j - a[i]] = true; 17 | } 18 | if (j + a[i] <= limit) { 19 | b[i + 1][j + a[i]] = true; 20 | } 21 | } 22 | } 23 | } 24 | 25 | for (int j = limit; j >= 0; --j) { 26 | if (b[n][j]) { 27 | return j; 28 | } 29 | } 30 | return -1; 31 | } 32 | -------------------------------------------------------------------------------- /D1L1/ChessMetric.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | typedef long long int64; 7 | 8 | int n; 9 | int64 dp[2][100][100]; 10 | int dx[] = {0, 0, 1, -1, 1, -1, 1, -1, 2, -2, 2, -2, 1, 1, -1, -1}, 11 | dy[] = {1, -1, 0, 0, 1, -1, -1, 1, 1, 1, -1, -1, 2, -2, 2, -2}; 12 | 13 | void clear(bool k) { 14 | for (int x = 0; x != n; ++x) { 15 | for (int y = 0; y != n; ++y) { 16 | dp[k][x][y] = 0; 17 | } 18 | } 19 | } 20 | 21 | int64 howMany(int size, 22 | vector const &start, 23 | vector const &end, 24 | int numMoves) { 25 | n = size; 26 | clear(0); dp[0][start[0]][start[1]] = 1; 27 | 28 | for (int m = 0; m < numMoves; ++m) { 29 | bool k = m % 2, k0 = !k; clear(k0); 30 | for (int x = 0; x != n; ++x) { 31 | for (int y = 0; y != n; ++y) { 32 | int64 w = dp[k][x][y]; 33 | if (w == 0) { 34 | continue; 35 | } 36 | for (int i = 0; i != 16; ++i) { 37 | int x0 = x + dx[i], y0 = y + dy[i]; 38 | if (x0 < 0 || y0 < 0 || x0 >= n || y0 >= n) { 39 | continue; 40 | } 41 | dp[k0][x0][y0] += w; 42 | } 43 | } 44 | } 45 | } 46 | 47 | return dp[numMoves % 2][end[0]][end[1]]; 48 | } 49 | -------------------------------------------------------------------------------- /D1L1/CombinationLock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | double degreesTurned(vector const &combo, int size, int start) { 5 | int n = combo.size(), pre = start, dir = 1; 6 | double inc = 360.0 / size, ret = n * (n + 1) * 180; 7 | for (int cur : combo) { 8 | int gap = (cur - pre) * dir; 9 | if (gap < 0) { 10 | gap = size + gap; 11 | } 12 | ret += inc * gap; 13 | pre = cur; dir *= (-1); 14 | } 15 | return ret; 16 | } 17 | -------------------------------------------------------------------------------- /D1L1/DateFormat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class Date { 8 | public: 9 | int day, month; 10 | Date (int day, int month) : day(day), month(month) { } 11 | bool operator < (Date const &date) const { 12 | if (month < date.month) return true; 13 | if (month > date.month) return false; 14 | return day < date.day; 15 | } 16 | bool operator <= (Date const &date) const { 17 | if (month < date.month) return true; 18 | if (month > date.month) return false; 19 | return day <= date.day; 20 | } 21 | Date& operator = (Date const &date) { 22 | day = date.day; 23 | month = date.month; 24 | return *this; 25 | } 26 | bool valid() const { 27 | return month <= 12; 28 | } 29 | }; 30 | istream& operator >> (istream &is, Date &date) { 31 | is >> date.day; is.ignore(1); is >> date.month; 32 | return is; 33 | } 34 | ostream& operator << (ostream &os, Date const &date) { 35 | os << setw(2) << setfill('0') << date.month << '/' 36 | << setw(2) << setfill('0') << date.day; 37 | return os; 38 | } 39 | 40 | string concat(vector v) { 41 | ostringstream oss; 42 | for (int i = 0; i < v.size(); ++i) 43 | oss << v[i]; 44 | return oss.str(); 45 | } 46 | string fromEuropeanToUs(vector const &dateList) 47 | { 48 | istringstream iss(concat(dateList)); ostringstream oss; 49 | Date prev(0, 0), cur(0, 0); 50 | while (true) { 51 | iss >> cur; 52 | Date temp(cur.month, cur.day); 53 | 54 | if (cur <= prev) { 55 | if (temp <= cur || temp <= prev) return ""; 56 | cur = temp; 57 | } 58 | else if (prev < temp && temp < cur) cur = temp; 59 | if (!cur.valid()) return ""; 60 | 61 | oss << cur; 62 | if (iss.good()) { 63 | oss << ' '; 64 | prev = cur; 65 | } 66 | else break; 67 | } 68 | return oss.str(); 69 | } 70 | -------------------------------------------------------------------------------- /D1L1/DateFormat.hs: -------------------------------------------------------------------------------- 1 | module DateFormat where 2 | import Text.Printf 3 | import Data.Maybe 4 | 5 | data Date = Date { day :: Int 6 | , month :: Int } 7 | instance Eq Date where 8 | (==) (Date d1 m1) (Date d2 m2) = d1 == d2 && m1 == m2 9 | instance Show Date where 10 | show (Date d m) = show' d ++ "/" ++ show' m 11 | where show' = printf "%02d" 12 | instance Ord Date where 13 | (<) (Date d1 m1) (Date d2 m2) = m1 < m2 || (m1 == m2 && d1 < d2) 14 | (<=) (Date d1 m1) (Date d2 m2) = m1 < m2 || (m1 == m2 && d1 <= d2) 15 | 16 | toDate :: String -> Date 17 | toDate [a,b,c,d,e] = Date (read [a,b]) (read [d,e]) 18 | 19 | rotateDate :: Date -> Date 20 | rotateDate (Date d m) = Date m d 21 | 22 | validDate :: Date -> Bool 23 | validDate (Date d m) = m <= 12 24 | 25 | fixDate :: Maybe Date -> Date -> Maybe Date 26 | fixDate Nothing _ = Nothing 27 | fixDate (Just prev) cur = 28 | if prev < cur then if validDate temp && temp < cur && prev < temp 29 | then Just temp 30 | else if validDate cur then Just cur 31 | else Nothing 32 | else if validDate temp && prev < temp 33 | then Just temp 34 | else Nothing 35 | where temp = rotateDate cur 36 | 37 | fixDates :: [Date] -> String 38 | fixDates ds = if length xs == length ds 39 | then unwords . map (show . rotateDate . fromJust) $ xs 40 | else "" 41 | where xs = tail . takeWhile isJust . scanl fixDate (Just (Date 0 0)) $ ds 42 | 43 | fromEuropeanToUs :: [String] -> String 44 | fromEuropeanToUs = fixDates . map toDate . words . concat 45 | -------------------------------------------------------------------------------- /D1L1/DateFormat.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | class Date implements Comparable { 4 | private int day, month; 5 | public Date(String str) { 6 | String[] parts = str.split("/"); 7 | int x = Integer.parseInt(parts[0]); 8 | int y = Integer.parseInt(parts[1]); 9 | if (x > y) { 10 | day = x; month = y; 11 | } 12 | else { 13 | day = y; month = x; 14 | } 15 | } 16 | 17 | public int getDay() { 18 | return day; 19 | } 20 | public int getMonth() { 21 | return month; 22 | } 23 | public void swap() { 24 | int temp = day; day = month; month = temp; 25 | } 26 | 27 | public int compareTo(Object o) { 28 | Date other = (Date) o; 29 | if (month < other.month) { 30 | return -1; 31 | } 32 | if (month == other.month) { 33 | if (day < other.day) { 34 | return -1; 35 | } 36 | if (day == other.day) { 37 | return 0; 38 | } 39 | return 1; 40 | } 41 | return 1; 42 | } 43 | 44 | private static String normalize(int n) { 45 | StringBuffer sb = new StringBuffer(); 46 | if (n < 10) { 47 | sb.append('0'); 48 | } 49 | sb.append(n); 50 | return sb.toString(); 51 | } 52 | public String toString() { 53 | StringBuffer sb = new StringBuffer(); 54 | sb.append(normalize(month)); 55 | sb.append('/'); 56 | sb.append(normalize(day)); 57 | return sb.toString(); 58 | } 59 | } 60 | 61 | public class DateFormat { 62 | public String join(String[] a) { 63 | StringBuffer sb = new StringBuffer(); 64 | for (int i = 0; i < a.length; ++i) { 65 | sb.append(a[i]); 66 | } 67 | return sb.toString(); 68 | } 69 | public String fromEuropeanToUs(String[] dateList) { 70 | String[] tokens = join(dateList).split(" "); 71 | 72 | Date[] dates = new Date[tokens.length]; 73 | dates[0] = new Date(tokens[0]); 74 | 75 | for (int i = 1; i < tokens.length; ++i) { 76 | dates[i] = new Date(tokens[i]); 77 | if (dates[i].compareTo(dates[i - 1]) <= 0) { 78 | if (dates[i].getDay() > 12) { 79 | return ""; 80 | } 81 | dates[i].swap(); 82 | if (dates[i].compareTo(dates[i - 1]) <= 0) { 83 | return ""; 84 | } 85 | } 86 | } 87 | 88 | StringBuffer sb = new StringBuffer(); 89 | sb.append(dates[0]).toString(); 90 | for (int i = 1; i < dates.length; ++i) { 91 | sb.append(' '); 92 | sb.append(dates[i].toString()); 93 | } 94 | return sb.toString(); 95 | } 96 | } -------------------------------------------------------------------------------- /D1L1/DigitPrime.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | bool prime[100]; 6 | 7 | void buildPrime() { 8 | memset(prime, true, 100); prime[0] = false; prime[1] = false; 9 | for (int i = 2; i < 100; ++i) { 10 | if (prime[i]) { 11 | for (int j = i + i; j < 100; j += i) { 12 | prime[j] = false; 13 | } 14 | } 15 | } 16 | } 17 | 18 | bool coolDigits(vector v) { 19 | for (int i = 0; i < v.size() - 1; ++i) { 20 | for (int j = i + 1; j < v.size(); ++j) { 21 | if (prime[10 * v[i] + v[j]] || prime[10 * v[j] + v[i]]) { 22 | return true; 23 | } 24 | } 25 | } 26 | return false; 27 | } 28 | 29 | vector toDigits(int n) { 30 | vector ret; 31 | while (n != 0) { 32 | int d = n % 10; 33 | if (d != 0) { 34 | ret.push_back(d); 35 | } 36 | n /= 10; 37 | } 38 | return ret; 39 | } 40 | 41 | int countNumbers(int a, int b) { 42 | buildPrime(); 43 | int ret = 0; 44 | for (int n = a; n <= b; ++n) { 45 | if (coolDigits(toDigits(n))) { 46 | ++ret; 47 | } 48 | } 49 | return ret; 50 | } 51 | -------------------------------------------------------------------------------- /D1L1/DropCoins.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int h, w; 7 | 8 | int area(vector const &board, int y1, int x1, int y2, int x2) { 9 | int n = 0; 10 | for (int y = y1; y <= y2; ++y) { 11 | for (int x = x1; x <= x2; ++x) { 12 | if (board[y][x] == 'o') { 13 | n += 1; 14 | } 15 | } 16 | } 17 | return n; 18 | } 19 | 20 | int cost(int y1, int x1, int y2, int x2) { 21 | int y3 = h - 1 - y2, x3 = w - 1 - x2; 22 | return x1 + y1 + x3 + y3 + min(x1, x3) + min(y1, y3); 23 | } 24 | 25 | int getMinimum(vector const &board, int k) { 26 | h = board.size(); w = board[0].size(); 27 | int n = area(board, 0, 0, h - 1, w - 1); 28 | if (k > n) { 29 | return -1; 30 | } 31 | if (k == n) { 32 | return 0; 33 | } 34 | int ret = 27000; 35 | for (int y1 = 0; y1 != h; ++y1) { 36 | for (int x1 = 0; x1 != w; ++x1) { 37 | for (int y2 = y1; y2 != h; ++y2) { 38 | for (int x2 = x1; x2 != w; ++x2) { 39 | if (area(board, y1, x1, y2, x2) == k) { 40 | int x = cost(y1, x1, y2, x2); 41 | if (x == 1) { 42 | return x; 43 | } 44 | if (x < ret) { 45 | ret = x; 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | return ret == 27000 ? -1 : ret; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /D1L1/DropCoins.hs: -------------------------------------------------------------------------------- 1 | module DropCoins where 2 | 3 | import Data.Array 4 | 5 | area :: Array Int (Array Int Char) -> Int -> Int -> Int -> Int -> Int 6 | area a y1 x1 y2 x2 = sum [ isCoin ((a!y)!x) | y <- [y1 .. y2] 7 | , x <- [x1 .. x2] ] 8 | where isCoin c = if c == 'o' then 1 9 | else 0 10 | 11 | 12 | cost :: Int -> Int -> Int -> Int -> Int -> Int -> Int 13 | cost h w y1 x1 y2 x2 = x1 + y1 + x3 + y3 + (min x1 x3) + (min y1 y3) 14 | where x3 = w - x2 15 | y3 = h - y2 16 | 17 | getMinimum :: [String] -> Int -> Int 18 | getMinimum board k = convert $ minimum [ best y1 x1 y2 x2 | y1 <- [0 .. h] 19 | , x1 <- [0 .. w] 20 | , y2 <- [y1 .. h] 21 | , x2 <- [x1 .. w] ] 22 | where h = (length board) - 1 23 | w = (length (head board)) - 1 24 | best y1 x1 y2 x2 = if area a y1 x1 y2 x2 == k then cost h w y1 x1 y2 x2 25 | else 27000 26 | convert x = if x == 27000 then -1 27 | else x 28 | a = fmap (listArray (0, w)) (listArray (0, h) board) 29 | -------------------------------------------------------------------------------- /D1L1/GeneralChess.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | typedef pair Pos; 9 | int dx[] = {-2, -2, -1, -1, 1, 1, 2, 2}, 10 | dy[] = {-1, 1, -2, 2, -2, 2, -1, 1}; 11 | 12 | string toString(Pos const &p) { 13 | ostringstream oss; 14 | oss << p.first << ',' << p.second; 15 | return oss.str(); 16 | } 17 | 18 | Pos toPos(string const &s) { 19 | istringstream iss(s); 20 | int y, x; iss >> x; iss.ignore(1); iss >> y; 21 | return make_pair(x, y); 22 | } 23 | 24 | vector knight(Pos const &p) { 25 | vector ret; 26 | for (int i = 0; i != 8; ++i) { 27 | int x = p.first + dx[i]; 28 | int y = p.second + dy[i]; 29 | ret.push_back(make_pair(x, y)); 30 | } 31 | return ret; 32 | } 33 | 34 | vector attackPositions(vector const &pieces) { 35 | int n = pieces.size(); 36 | 37 | vector poses(n); 38 | transform(begin(pieces), end(pieces), begin(poses), toPos); 39 | 40 | vector> valids(n); 41 | transform(begin(poses), end(poses), begin(valids), knight); 42 | 43 | vector common(valids[0]); 44 | auto first = common.begin(), last = common.end(); 45 | for (int i = 1; i < n; ++i) { 46 | last = remove_if(first, last, [&](Pos const &p) -> bool { 47 | return !binary_search(begin(valids[i]), end(valids[i]), p); 48 | }); 49 | } 50 | 51 | vector ret(last - first); 52 | transform(first, last, begin(ret), toString); 53 | 54 | return ret; 55 | } 56 | -------------------------------------------------------------------------------- /D1L1/GirlsAndBoys.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int arrange(string const &a, char c) { 7 | int ret = 0; 8 | for (int i = 0, n = 0; i != a.size(); ++i) { 9 | if (a[i] == c) { 10 | ret += i - n; 11 | ++n; 12 | } 13 | } 14 | return ret; 15 | } 16 | 17 | int sortThem(string const &row) { 18 | return min(arrange(row, 'G'), arrange(row, 'B')); 19 | } 20 | -------------------------------------------------------------------------------- /D1L1/HouseBuilding.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int effort(vector a, int target) { 7 | int ret = 0; 8 | for (int x : a) { 9 | ret += min(abs(x - target), abs(target - 1 - x)); 10 | } 11 | return ret; 12 | } 13 | 14 | int getMinimum(vector const &area) { 15 | vector a; 16 | for (int i = 0; i != area.size(); ++i) { 17 | for (int j = 0; j != area[i].size(); ++j) { 18 | a.push_back(area[i][j] - '0'); 19 | } 20 | } 21 | 22 | int ret = 9 * 50 * 50; 23 | for (int target = 1; target <= 9; ++target) { 24 | ret = min(ret, effort(a, target)); 25 | } 26 | return ret; 27 | } 28 | -------------------------------------------------------------------------------- /D1L1/IPConverter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | bool ok(string const &part) { 9 | if (part[0] == '0') { 10 | return part.size() == 1; 11 | } 12 | return atoi(part.data()) <= 255; 13 | } 14 | 15 | vector possibleAddresses(string const &ip) { 16 | vector ret; 17 | for (int a = 1; a <= 3; ++a) { 18 | for (int b = 1; b <= 3; ++b) { 19 | for (int c = 1; c <= 3; ++c) { 20 | for (int d = 1; d <= 3; ++d) { 21 | if (a + b + c + d != ip.size()) { 22 | continue; 23 | } 24 | string x = ip.substr(0, a), 25 | y = ip.substr(a, b), 26 | z = ip.substr(a + b, c), 27 | w = ip.substr(a + b + c, d); 28 | if (ok(x) && ok(y) && ok(z) && ok(w)) { 29 | ostringstream oss; 30 | oss << x << '.' << y << '.' << z << '.' << w; 31 | ret.push_back(oss.str()); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | sort(begin(ret), end(ret)); 38 | return ret; 39 | } 40 | -------------------------------------------------------------------------------- /D1L1/InterestingDigits.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int sumDigits(int n, int base) { 6 | int ret = 0; 7 | while (n > 0) { 8 | ret += (n % base); 9 | n /= base; 10 | } 11 | return ret; 12 | } 13 | 14 | bool cool(int digit, int base) { 15 | int max = base * base * base * base; 16 | for (int i = digit + digit; i < max; i += digit) { 17 | if (sumDigits(i, base) % digit != 0) { 18 | return false; 19 | } 20 | } 21 | return true; 22 | } 23 | 24 | vector digits(int base) { 25 | vector ret; 26 | for (int i = 2; i != base; ++i) { 27 | if (cool(i, base)) { 28 | ret.push_back(i); 29 | } 30 | } 31 | return ret; 32 | } 33 | -------------------------------------------------------------------------------- /D1L1/IsomorphicWords.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | bool isIsormorphic(string const &x, string const &y) { 7 | map a; 8 | vector b(26, false); 9 | for (int i = 0; i != x.size(); ++i) { 10 | auto it = a.find(x[i]); 11 | if (it == a.end()) { 12 | int j = y[i] - 'a'; 13 | if (b[j]) { 14 | return false; 15 | } 16 | a[x[i]] = y[i]; 17 | b[j] = true; 18 | } else if (it->second != y[i]) { 19 | return false; 20 | } 21 | } 22 | return true; 23 | } 24 | 25 | int countPairs(vector const &words) { 26 | int ret = 0; 27 | for (int i = 0; i < words.size() - 1; ++i) { 28 | for (int j = i + 1; j < words.size(); ++j) { 29 | ret += isIsormorphic(words[i], words[j]); 30 | } 31 | } 32 | return ret; 33 | } 34 | -------------------------------------------------------------------------------- /D1L1/LameKnight.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int maxCells(int h, int w) { 7 | if (h == 1 || w == 1) return 1; 8 | if (h == 2) return min(4, (w + 1)/2); 9 | if (w >= 7) return w - 2; 10 | return min(4, w); 11 | } 12 | -------------------------------------------------------------------------------- /D1L1/LameKnight.hs: -------------------------------------------------------------------------------- 1 | module LameKnight where 2 | 3 | maxCells :: Int -> Int -> Int 4 | maxCells 1 _ = 1 5 | maxCells _ 1 = 1 6 | maxCells 2 w = min 4 $ div (w + 1) 2 7 | maxCells h w | w < 7 = min 4 w 8 | | otherwise = w - 2 9 | -------------------------------------------------------------------------------- /D1L1/LameKnight.java: -------------------------------------------------------------------------------- 1 | public class LameKnight { 2 | public int maxCells(int height, 3 | int width) { 4 | if (height == 1 || width == 1) { 5 | return 1; 6 | } 7 | if (height == 2) { 8 | return Math.min(4, (width + 1)/2); 9 | } 10 | if (width >= 7) { 11 | return width - 2; 12 | } 13 | return Math.min(4, width); 14 | } 15 | } -------------------------------------------------------------------------------- /D1L1/LuckyRemainder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | void digitize(string const &s, vector &v) { 7 | v.resize(s.size()); 8 | transform(s.begin(), s.end(), v.begin(), [](char c) { return c - '0'; }); 9 | } 10 | int pow2mod9(int n) { 11 | static int cycles[] = {1, 2, 4, 8, 7, 5}; 12 | return cycles[n % 6]; 13 | } 14 | int getLuckyRemainder(string const &X) { 15 | vector v; digitize(X, v); 16 | int sum = accumulate(v.begin(), v.end(), 0); 17 | return ((sum % 9) * pow2mod9(v.size() - 1)) % 9; 18 | } 19 | -------------------------------------------------------------------------------- /D1L1/LuckyRemainder.hs: -------------------------------------------------------------------------------- 1 | module LuckyRemainder where 2 | import Data.Char 3 | 4 | pow2mod9 :: Int -> Int 5 | pow2mod9 0 = 1 6 | pow2mod9 1 = 2 7 | pow2mod9 2 = 4 8 | pow2mod9 3 = 8 9 | pow2mod9 4 = 7 10 | pow2mod9 5 = 5 11 | pow2mod9 n = pow2mod9 $ mod n 6 12 | 13 | luckyRemainder :: [Int] -> Int 14 | luckyRemainder ds = mod (mod (sum ds) 9 * pow2mod9 (length ds - 1)) 9 15 | 16 | getLuckyRemainder :: String -> Int 17 | getLuckyRemainder = luckyRemainder . map toDigit 18 | where toDigit c = ord c - ord '0' 19 | -------------------------------------------------------------------------------- /D1L1/LuckyRemainder.java: -------------------------------------------------------------------------------- 1 | public class LuckyRemainder { 2 | public int pow2mod9(int n) { 3 | switch (n % 6) { 4 | case 0 : return 1; 5 | case 1 : return 2; 6 | case 2 : return 4; 7 | case 3 : return 8; 8 | case 4 : return 7; 9 | case 5 : return 5; 10 | } 11 | return 0; 12 | } 13 | public int getLuckyRemainder(String X) { 14 | int sum = 0; 15 | for (int i = 0; i < X.length(); ++i) { 16 | sum += X.charAt(i) - '0'; 17 | } 18 | sum %= 9; 19 | return (sum * pow2mod9(X.length() - 1)) % 9; 20 | } 21 | } -------------------------------------------------------------------------------- /D1L1/MinimumLiars.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int getMinimum(vector a) { 7 | sort(a.begin(), a.end()); 8 | int n = a.size(); 9 | if (a[n - 1] == 0) { 10 | return 0; 11 | } 12 | for (int ret = 1; ret <= n; ++ret) { 13 | int pos = n - ret; 14 | if (a[pos] > ret) { 15 | if (pos == 0 || a[pos - 1] <= ret) { 16 | return ret; 17 | } 18 | } 19 | } 20 | return -1; 21 | } 22 | -------------------------------------------------------------------------------- /D1L1/MissingParentheses.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int countCorrections(string const &par) { 6 | int p = 0, q = 0; 7 | for (int i = 0; i != par.size(); ++i) { 8 | if (par[i] == '(') { 9 | ++p; 10 | } else { 11 | if (p == 0) { 12 | ++q; 13 | } else { 14 | --p; 15 | } 16 | } 17 | } 18 | return p + q; 19 | } 20 | -------------------------------------------------------------------------------- /D1L1/MissingParentheses.hs: -------------------------------------------------------------------------------- 1 | module MissingParentheses where 2 | 3 | countCorrections :: String -> Int 4 | countCorrections par = f par 0 0 5 | where f [] p q = p + q 6 | f ('(':xs) p q = f xs (p + 1) q 7 | f (')':xs) p q = if p > 0 then f xs (p - 1) q 8 | else f xs p (q + 1) 9 | -------------------------------------------------------------------------------- /D1L1/NextNumber.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | // See: 6 | // http://apps.topcoder.com/forums/?module=Thread&threadID=623482&start=0 7 | 8 | int getNextNumber(int N) { 9 | // Suppose N = 10101110 10 | int a = N & (-N); // a = 00000010 11 | int b = N + a; // b = 10110000 12 | int c = N ^ b; // c = 00011110 13 | int d = c / a; // d = 00001111 14 | int e = d >> 2; // e = 00000011 15 | return b | e; // ret = 10110011 16 | } 17 | -------------------------------------------------------------------------------- /D1L1/OneFight.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct Monster { 6 | int hp; 7 | int dp; 8 | }; 9 | bool operator< (Monster const &x, Monster const &y) { 10 | return x.hp * y.dp < y.hp * x.dp; 11 | } 12 | 13 | int monsterKilling(vector const &life, 14 | vector const &damage, 15 | int yourDamage) { 16 | int n = life.size(); 17 | 18 | vector ms; 19 | for (int i = 0; i != n; ++i) { 20 | Monster m = {(life[i] + yourDamage - 1)/yourDamage, damage[i]}; 21 | ms.push_back(m); 22 | } 23 | sort(begin(ms), end(ms)); 24 | 25 | int sum = accumulate(begin(damage), end(damage), 0), ret = 0; 26 | for (auto m : ms) { 27 | ret += m.hp * sum; 28 | sum -= m.dp; 29 | } 30 | return ret + 1; 31 | } 32 | -------------------------------------------------------------------------------- /D1L1/OrderedNim.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | string winner(vector const &a) { 5 | int i = 0; 6 | while (i < a.size() && a[i] == 1) { 7 | ++i; 8 | } 9 | return (i % 2 == 0) ^ (i == a.size()) ? "Alice" : "Bob"; 10 | } 11 | -------------------------------------------------------------------------------- /D1L1/OrthogonalAnagram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int a[256], d[256]; 7 | char b[50], c[50]; 8 | int n; 9 | 10 | bool impossible(int k) { 11 | int len = n - k; 12 | fill(d, d + 256, 0); 13 | for (char *p = b + k; p != b + n; ++p) { 14 | ++d[*p]; 15 | if (d[*p] + a[*p] > len) { 16 | return true; 17 | } 18 | } 19 | return false; 20 | } 21 | 22 | bool recurse(int k) { 23 | if (k == n) { 24 | return true; 25 | } 26 | if (impossible(k)) { 27 | return false; 28 | } 29 | for (int i = 'a'; i <= 'z'; ++i) { 30 | if (a[i] == 0 || i == b[k]) { 31 | continue; 32 | } 33 | --a[i]; 34 | c[k] = i; 35 | if (recurse(k + 1)) { 36 | return true; 37 | } 38 | ++a[i]; 39 | } 40 | } 41 | 42 | string solve(string const &s) { 43 | n = s.size(); 44 | copy(s.begin(), s.end(), b); 45 | 46 | fill(a, a + 256, 0); 47 | for (auto it = s.begin(); it != s.end(); ++it) { 48 | ++a[*it]; 49 | } 50 | 51 | return recurse(0) ? string(c, n) : ""; 52 | } 53 | -------------------------------------------------------------------------------- /D1L1/PerfectPermutation.cpp: -------------------------------------------------------------------------------- 1 | // The key to solve this problem is the concept Permutation Cycles 2 | 3 | #include 4 | using namespace std; 5 | 6 | int reorder(vector const &a) { 7 | int ret = 0, n = a.size(); 8 | vector seen(n, false); 9 | for (int i = 0; i != n; ++i) { 10 | if (!seen[i]) { 11 | ++ret; 12 | for (int j = i; !seen[j]; j = a[j]) { 13 | seen[j] = true; 14 | } 15 | } 16 | } 17 | return ret == 1 ? 0 : ret; 18 | } 19 | -------------------------------------------------------------------------------- /D1L1/PeriodicJumping.hs: -------------------------------------------------------------------------------- 1 | -- Start with D2L2 Jumping first 2 | module PeriodicJumping where 3 | 4 | type Range = (Int, Int) 5 | 6 | -- Refer to D2L2 Jumping for intimacy with the problem 7 | jump :: Range -> Int -> Range 8 | jump (lo, hi) d | d <= lo = (lo - d, hi + d) 9 | | d <= hi = (0 , hi + d) 10 | | otherwise = (d - hi, hi + d) 11 | 12 | -- In step one, we jump as many double cycles of jumpLengths as possible 13 | -- Notice that the code already covers the case p == 0 14 | stepOne :: Int -> [Int] -> (Int, Range) 15 | stepOne target ds = (p * (2 * length ds), (0, target - q)) where 16 | (p, q) = target `divMod` (2 * sum ds) 17 | 18 | -- The problem is then reduced to D2L2 Jumping except that we start with an 19 | -- initial range we got from stepOne instead of (0, 0) 20 | stepTwo :: Int -> Range -> [Int] -> Int 21 | stepTwo target (lo, hi) = length . takeWhile notYet . 22 | scanl jump (lo, hi) . cycle where 23 | notYet (lo, hi) = target < lo || target > hi 24 | 25 | -- The verbosity is intended for clarity 26 | minimalTime :: Int -> [Int] -> Int 27 | minimalTime x jumpLengths = stepOneTime + 28 | stepTwo target stepOneRange jumpLengths where 29 | target = abs x 30 | (stepOneTime, stepOneRange) = stepOne target jumpLengths 31 | -------------------------------------------------------------------------------- /D1L1/RedSquare.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int countTheEmptyReds(int maxRank, 5 | int maxFile, 6 | vector const &rank, 7 | vector const &file) { 8 | int q = 1 - ((maxFile + 1) % 2); 9 | int reds = (maxRank * maxFile) / 2; 10 | for (int i = 0; i != rank.size(); ++i) { 11 | if ((rank[i] + file[i]) % 2 == q) { 12 | --reds; 13 | } 14 | } 15 | return reds; 16 | } 17 | -------------------------------------------------------------------------------- /D1L1/RoadConstruction.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int getExitTime(vector const &a) { 7 | int n = a.size(); 8 | int is[n]; fill(is, is + n, 0); 9 | bool ys[n]; fill(ys, ys + n, false); 10 | 11 | for (int ret = 0;; ++ret) { 12 | int j = 0, k = 0; 13 | for (; j != n; ++j) { 14 | if (ys[j]) { 15 | break; 16 | } 17 | if (is[j] < a[j].size()) { 18 | ys[j] = true; 19 | k = j; 20 | } 21 | } 22 | if (j == n) { 23 | j = k; 24 | } 25 | if (a[j][is[j]] == 'D') { 26 | return ret; 27 | } 28 | ++is[j]; 29 | ys[j] = false; 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /D1L1/SlimeXSlimesCity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int merge(vector &a) { 7 | sort(a.begin(), a.end()); 8 | int n = a.size() - 1, top = a[n]; 9 | for (int i = 0; i != n; ++i) { 10 | int sum = a[i]; 11 | for (int j = 0; sum < top; ++j) { 12 | if (j == i) continue; 13 | if (sum < a[j]) break; 14 | sum += a[j]; 15 | } 16 | if (sum >= top) return n - i + 1; 17 | } 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /D1L1/SlimeXSlimesCity.hs: -------------------------------------------------------------------------------- 1 | module SlimeXSlimesCity where 2 | import Data.List 3 | import Data.Maybe 4 | 5 | possibleName :: Int -> [Int] -> Int -> Bool 6 | possibleName target xs k = (foldl (addExcept k) (xs!!k) $ zip [0..] xs) >= target 7 | where addExcept k acc (i, x) = if i == k then acc 8 | else if acc >= x then acc + x 9 | else acc 10 | 11 | mergeSorted :: [Int] -> Int 12 | mergeSorted xs = length xs - (fst . fromJust . find snd . zip [0..] . 13 | map (possibleName (last xs) xs) $ [0..]) 14 | 15 | merge :: [Int] -> Int 16 | merge = mergeSorted . sort 17 | -------------------------------------------------------------------------------- /D1L1/SlimeXSlimesCity.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class SlimeXSlimesCity { 4 | public int merge(int[] a) { 5 | Arrays.sort(a); 6 | int n = a.length, 7 | top = a[n - 1]; 8 | for (int i = 0; i < n - 1; ++i) { 9 | int sum = a[i]; 10 | for (int j = 0; sum < top; ++j) { 11 | if (j == i) continue; 12 | if (sum >= a[j]) sum += a[j]; 13 | else break; 14 | } 15 | if (sum >= top) return n - i; 16 | } 17 | return 1; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /D1L1/Spamatronic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | void tokenize(set &tokens, string const &st) { 9 | ostringstream oss; 10 | for (int i = 0; i != st.size(); ++i) 11 | if (isalpha(st[i])) 12 | oss << toupper(st[i]); 13 | else if (!oss.str().empty()) { 14 | tokens.insert(oss.str()); 15 | oss.str(""); 16 | } 17 | if (!oss.str().empty()) 18 | tokens.insert(oss.str()); 19 | } 20 | vector filter(vector const &knownSpam, 21 | vector const &newMail) { 22 | vector ret; set spams; 23 | for (auto it = knownSpam.begin(); it != knownSpam.end(); ++it) 24 | tokenize(spams, *it); 25 | for (int i = 0; i != newMail.size(); ++i) { 26 | set tokens; tokenize(tokens, newMail[i]); int k = 0; 27 | for (auto it = tokens.begin(); it != tokens.end(); ++it) 28 | if (spams.find(*it) != spams.end()) 29 | ++k; 30 | if (tokens.size() * 3 <= k * 4) 31 | for (auto it = tokens.begin(); it != tokens.end(); ++it) 32 | spams.insert(*it); 33 | else ret.push_back(i); 34 | } 35 | return ret; 36 | } 37 | -------------------------------------------------------------------------------- /D1L1/Spamatronic.hs: -------------------------------------------------------------------------------- 1 | module Spamatronic where 2 | import Data.Char 3 | import Data.Set (Set) 4 | import qualified Data.Set as Set 5 | import Data.List.Split 6 | 7 | tokenize :: String -> Set String 8 | tokenize = foldl (flip Set.insert) Set.empty . 9 | map (map toUpper) . wordsBy (not . isLetter) 10 | 11 | isSpam :: Set String -> Set String -> Bool 12 | isSpam inner outer = 3 * n <= 4 * k 13 | where k = Set.size $ Set.intersection inner outer 14 | n = Set.size inner 15 | 16 | filterSpam :: [String] -> [String] -> [Int] 17 | filterSpam knownSpam newMail = 18 | snd . foldl pair (Set.unions . map tokenize $ knownSpam, []) . 19 | zip (iterate (+1) 0) . map tokenize $ newMail 20 | where pair (spams, ret) (i, mail) = 21 | if isSpam mail spams then (Set.union mail spams, ret) 22 | else (spams, ret ++ [i]) -------------------------------------------------------------------------------- /D1L1/Spamatronic.java: -------------------------------------------------------------------------------- 1 | import java.util.Set; 2 | import java.util.HashSet; 3 | import java.util.List; 4 | import java.util.ArrayList; 5 | import java.util.Iterator; 6 | 7 | public class Spamatronic { 8 | public void tokenize(Set tokens, String source) { 9 | String[] parts = source.split("[^a-zA-Z]"); 10 | for (int i = 0; i < parts.length; ++i) { 11 | if (!parts[i].isEmpty()) { 12 | tokens.add(parts[i].toLowerCase()); 13 | } 14 | } 15 | } 16 | public boolean isSpam(Set spams, Set tokens) { 17 | int count = 0; 18 | Iterator it = tokens.iterator(); 19 | while (it.hasNext()) { 20 | if (spams.contains(it.next())) { 21 | ++count; 22 | } 23 | } 24 | return (count * 4) >= (tokens.size() * 3); 25 | } 26 | public int[] filter(String[] knownSpam, 27 | String[] newMail) { 28 | Set spams = new HashSet(); 29 | for (int i = 0; i < knownSpam.length; ++i) { 30 | tokenize(spams, knownSpam[i]); 31 | } 32 | 33 | List indexes = new ArrayList(); 34 | for (int i = 0; i < newMail.length; ++i) { 35 | Set tokens = new HashSet(); 36 | tokenize(tokens, newMail[i]); 37 | if (isSpam(spams, tokens)) { 38 | Iterator it = tokens.iterator(); 39 | while (it.hasNext()) { 40 | spams.add(it.next()); 41 | } 42 | } 43 | else { 44 | indexes.add(i); 45 | } 46 | } 47 | 48 | int[] ret = new int[indexes.size()]; 49 | for (int i = 0; i < indexes.size(); ++i) { 50 | ret[i] = indexes.get(i).intValue(); 51 | } 52 | return ret; 53 | } 54 | } -------------------------------------------------------------------------------- /D1L1/SpiralNumbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int sqr(int x) { 8 | return x * x; 9 | } 10 | 11 | int compute(int n, int &k, int &p, int &q) { 12 | int x = floor(sqrt((double) n)); 13 | k = (x - 1)/2; 14 | if (sqr(x) == n) { 15 | --k; 16 | } 17 | int m = n - (sqr(2*k + 1) + 1); 18 | int r = 2*k + 2; 19 | p = m / r; q = m % r; 20 | } 21 | 22 | void spiral(int n, int &y, int &x) { 23 | int k, p, q; compute(n, k, p, q); 24 | switch (p) { 25 | case 0: 26 | x = k + 1; 27 | y = (-k) + q; 28 | break; 29 | case 1: 30 | y = k + 1; 31 | x = k - q; 32 | break; 33 | case 2: 34 | x = -(k + 1); 35 | y = k - q; 36 | break; 37 | case 3: 38 | y = -(k + 1); 39 | x = (-k) + q; 40 | } 41 | } 42 | 43 | string getPosition(int N) { 44 | if (N == 1) { 45 | return "(0,0)"; 46 | } 47 | int y, x; spiral(N, y, x); 48 | ostringstream oss; 49 | oss << '(' << y << ',' << x << ')'; 50 | return oss.str(); 51 | } 52 | -------------------------------------------------------------------------------- /D1L1/StrongPrimePower.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | bool is_prime(int n) { 8 | for (int i = 2; (i * i) <= n; ++i) 9 | if (n % i == 0) return false; 10 | return true; 11 | } 12 | long long bin_pow(int p, int q) { 13 | if (q == 0) return 1; 14 | if (q == 1) return p; 15 | long long n = bin_pow(p, q / 2); 16 | return n * n * bin_pow(p, q % 2); 17 | } 18 | vector base_exp(long long n) { 19 | int retp, retq = 1; 20 | 21 | for (int q = 2; retq == 1 && q != 60; ++q) { 22 | int p = round(pow(n, 1.0 / q)); 23 | if (is_prime(p) && bin_pow(p, q) == n) { 24 | retp = p; 25 | retq = q; 26 | } 27 | } 28 | 29 | vector ret; 30 | if (retq > 1) { 31 | ret.push_back(retp); 32 | ret.push_back(retq); 33 | return ret; 34 | } 35 | else return ret; 36 | } 37 | vector baseAndExponent(string const &n) { 38 | long long x; istringstream iss(n); iss >> x; 39 | return base_exp(x); 40 | } 41 | -------------------------------------------------------------------------------- /D1L1/StrongPrimePower.hs: -------------------------------------------------------------------------------- 1 | module StrongPrimePower where 2 | import Data.List 3 | import Data.Maybe 4 | 5 | isPrime :: Int -> Bool 6 | isPrime n = null . filter (\i -> mod n i == 0) . 7 | takeWhile (\i -> i * i <= n) $ [2..] 8 | 9 | baseExp :: Integer -> [Int] 10 | baseExp n = concatMap tupleToList . maybeToList . find (check n) . 11 | filter (isPrime . fst) . map (getPQ n) $ [2..59] 12 | where getPQ n q = (round $ (fromIntegral n) ** (1.0 / (fromIntegral q)), q) 13 | check n (p, q) = (fromIntegral p) ^ q == n 14 | tupleToList (p, q) = [p, q] 15 | 16 | baseAndExponent :: String -> [Int] 17 | baseAndExponent s = baseExp (read s :: Integer) 18 | -------------------------------------------------------------------------------- /D1L1/StrongPrimePower.java: -------------------------------------------------------------------------------- 1 | public class StrongPrimePower { 2 | public static boolean isPrime(int n) { 3 | for (int i = 2; (i * i) <= n; ++i) { 4 | if (n % i == 0) { 5 | return false; 6 | } 7 | } 8 | return true; 9 | } 10 | public long naturalPow(int p, int q) { 11 | if (q == 1) { 12 | return p; 13 | } 14 | if (q == 0) { 15 | return 1; 16 | } 17 | long sqrt = naturalPow(p, q / 2); 18 | return sqrt * sqrt * naturalPow(p, q % 2); 19 | } 20 | public int[] pair(int p, int q) { 21 | int[] ret = new int[2]; 22 | ret[0] = p; ret[1] = q; 23 | return ret; 24 | } 25 | public int[] baseAndExponent(String number) { 26 | Long n = Long.parseLong(number); 27 | for (int q = 2; q < 60; ++q) { 28 | double pp = Math.pow((double) n, 1.0 / q); 29 | int p = (int) Math.round(pp); 30 | if (isPrime(p) && naturalPow(p, q) == n) { 31 | return pair(p, q); 32 | } 33 | } 34 | return new int[0]; 35 | } 36 | } -------------------------------------------------------------------------------- /D1L1/TallPeople.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | vector> a; 8 | 9 | void parse(vector const &people) { 10 | for (auto row : people) { 11 | vector v; 12 | istringstream iss(row); 13 | while (iss.good()) { 14 | int j; iss >> j; v.push_back(j); 15 | } 16 | a.push_back(v); 17 | } 18 | } 19 | 20 | vector getPeople(vector const &people) { 21 | parse(people); 22 | int tallest = 0, shortest = 1001; 23 | for (auto row : a) { 24 | tallest = max(tallest, *min_element(begin(row), end(row))); 25 | } 26 | for (int x = 0; x != a[0].size(); ++x) { 27 | int cur = 0; 28 | for (int y = 0; y != a.size(); ++y) { 29 | cur = max(cur, a[y][x]); 30 | } 31 | shortest = min(shortest, cur); 32 | } 33 | return {tallest, shortest}; 34 | } 35 | -------------------------------------------------------------------------------- /D1L1/TheSquareRootDilemma.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int countPairs(int N, int M) { 4 | int ret = 0; 5 | for (int A = 1; A <= N; ++A) { 6 | /* 7 | We need to find the number of B such that A * B is a perfect square. 8 | Now assume: 9 | - sqA is the largest perfect square such that A divides sqA 10 | - sqB is the largest perfect square such that A divides sqB 11 | - a = A/sqA 12 | - b = B/sqB 13 | We can easily find sqA and then a. 14 | Since a * b has to be a perfect square, we can deduce that b = a. 15 | */ 16 | int sqA = 1; 17 | for (int i = 2; ; ++i) { 18 | int ii = i * i; 19 | if (ii > A) { 20 | break; 21 | } 22 | if (A % ii == 0) { 23 | sqA = ii; 24 | } 25 | } 26 | int a = A/sqA; 27 | ret += floor(sqrt(M/a)); 28 | } 29 | return ret; 30 | } 31 | -------------------------------------------------------------------------------- /D1L1/ThirtyOne.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | vector parse(string hand) { 7 | vector cards(3); 8 | istringstream iss(hand); iss >> cards[0] >> cards[1] >> cards[2]; 9 | return cards; 10 | } 11 | 12 | int convert(string card) { 13 | switch (card[0]) { 14 | case 'A': return 11; 15 | case 'J': 16 | case 'Q': 17 | case 'K': return 10; 18 | default : int ret; istringstream(card) >> ret; return ret; 19 | } 20 | } 21 | 22 | int value(vector const &cards) { 23 | if (cards[0] == cards[1] && cards[1] == cards[2]) { 24 | return 61; 25 | } 26 | vector a(3); 27 | transform(begin(cards), end(cards), begin(a), convert); 28 | int sum = accumulate(begin(a), end(a), 0); 29 | return sum == 32 ? 44 : (2 * sum); 30 | } 31 | 32 | int findWinner(vector const &hands) { 33 | int best = 0, ret = 0; 34 | for (int i = 0; i != hands.size(); ++i) { 35 | int cur = value(parse(hands[i])); 36 | if (cur > best) { 37 | best = cur; 38 | ret = i; 39 | } 40 | } 41 | return ret; 42 | } 43 | -------------------------------------------------------------------------------- /D1L1/Underprimes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int howMany(int A, int B) { 5 | // a[i] is the number of prime factors of i 6 | // if a[i] = 0, i is a prime 7 | vector a(B + 1, 0); 8 | a[0] = a[1] = 1; 9 | 10 | for (int i = 2; i <= B; ++i) { 11 | if (a[i] == 0) { 12 | for (int j = i + i; j <= B; j += i) { 13 | for (int k = j; k % i == 0; k /= i) { 14 | ++a[j]; 15 | } 16 | } 17 | } 18 | } 19 | 20 | int ret = 0; 21 | for (int i = A; i <= B; ++i) { 22 | if (a[a[i]] == 0) { 23 | ++ret; 24 | } 25 | } 26 | return ret; 27 | } 28 | -------------------------------------------------------------------------------- /D1L1/WindowManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int H, W; 7 | vector a; 8 | 9 | void drawInside(int y1, int x1, int y2, int x2, char c) { 10 | y1 = max(0, y1); x1 = max(0, x1); 11 | y2 = min(y2, H - 1); x2 = min(x2, W - 1); 12 | for (int y = y1; y <= y2; ++y) { 13 | for (int x = x1; x <= x2; ++x) { 14 | a[y][x] = c; 15 | } 16 | } 17 | } 18 | 19 | void drawHorizontal(int y, int x1, int x2) { 20 | if (y < 0 || y >= H) { 21 | return; 22 | } 23 | x1 = max(0, x1); x2 = min(W - 1, x2); 24 | for (int x = x1; x <= x2 ; ++x) { 25 | a[y][x] = '-'; 26 | } 27 | } 28 | 29 | void drawVertical(int x, int y1, int y2) { 30 | if (x < 0 || x >= W) { 31 | return; 32 | } 33 | y1 = max(0, y1); y2 = min(H - 1, y2); 34 | for (int y = y1; y <= y2; ++y) { 35 | a[y][x] = '|'; 36 | } 37 | } 38 | 39 | void drawCorner(int y, int x) { 40 | if (y < 0 || y >= H || x < 0 || x >= W) { 41 | return; 42 | } 43 | a[y][x] = '+'; 44 | } 45 | 46 | void drawBorder(int y1, int x1, int y2, int x2) { 47 | drawVertical(x1, y1, y2); 48 | drawVertical(x2, y1, y2); 49 | drawHorizontal(y1, x1, x2); 50 | drawHorizontal(y2, x1, x2); 51 | drawCorner(y1, x1); 52 | drawCorner(y1, x2); 53 | drawCorner(y2, x1); 54 | drawCorner(y2, x2); 55 | } 56 | 57 | vector screen(int height, int width, vector const &wins) { 58 | H = height; W = width; a.assign(H, string(W, ' ')); 59 | for (auto win : wins) { 60 | istringstream iss(win); 61 | int y, x, h, w; char c; iss >> y >> x >> h >> w >> c; 62 | int y1 = y, x1 = x, y2 = y + h - 1, x2 = x + w - 1; 63 | drawInside(y1 + 1, x1 + 1, y2 - 1, x2 - 1, c); 64 | drawBorder(y1, x1, y2, x2); 65 | } 66 | return a; 67 | } 68 | -------------------------------------------------------------------------------- /D1L1/WordCompositionGame.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | void analyse(map &dic, vector const &list) { 8 | for (auto word : list) { 9 | ++dic[word]; 10 | } 11 | } 12 | 13 | int compute(map &dic, vector const &list) { 14 | int ret = 0; 15 | for (auto word : list) { 16 | ret += (4 - dic[word]); 17 | } 18 | return ret; 19 | } 20 | 21 | string score(vector const &listA, 22 | vector const &listB, 23 | vector const &listC) { 24 | map dic; 25 | analyse(dic, listA); 26 | analyse(dic, listB); 27 | analyse(dic, listC); 28 | 29 | ostringstream oss; 30 | oss << compute(dic, listA) << '/' 31 | << compute(dic, listB) << '/' 32 | << compute(dic, listC); 33 | return oss.str(); 34 | } 35 | -------------------------------------------------------------------------------- /D1L1/ZigZag.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int longestZigZag(vector const &a) { 6 | int n = a.size(), dp[n][2]; 7 | for (int i = 0; i != n; ++i) { 8 | for (int j = 0; j != 2; ++j) { 9 | dp[i][j] = 1; 10 | } 11 | } 12 | for (int i = 1; i < n; ++i) { 13 | for (int j = 0; j != i; ++j) { 14 | if (a[j] > a[i]) { 15 | dp[i][0] = max(dp[i][0], 1 + dp[j][1]); 16 | } else if (a[j] < a[i]) { 17 | dp[i][1] = max(dp[i][1], 1 + dp[j][0]); 18 | } 19 | } 20 | } 21 | return max(dp[n - 1][0], dp[n - 1][1]); 22 | } 23 | -------------------------------------------------------------------------------- /D1L2/BombMan.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct Node { 8 | int x, y, b, t; 9 | }; 10 | bool operator < (Node const &p, Node const &q) { 11 | return p.t > q.t; 12 | } 13 | 14 | int shortestPath(vector const &maze, int bombs) { 15 | int h = maze.size(), 16 | w = maze[0].size(), 17 | x0, y0; 18 | 19 | for (int y = 0; y != h; ++y) { 20 | for (int x = 0; x != w; ++x) { 21 | if (maze[y][x] == 'B') { 22 | x0 = x; 23 | y0 = y; 24 | } 25 | } 26 | } 27 | 28 | priority_queue nodes; 29 | Node init = {x0, y0, bombs, 0}; 30 | nodes.push(init); 31 | 32 | bool done[h][w][bombs + 1]; 33 | memset(done, false, sizeof(done)); 34 | 35 | int dx[] = {-1, 1, 0, 0}, 36 | dy[] = { 0, 0, -1, 1}; 37 | 38 | while (!nodes.empty()) { 39 | Node cur = nodes.top(); nodes.pop(); 40 | int x = cur.x, y = cur.y, b = cur.b, t = cur.t; 41 | if (done[y][x][b]) { 42 | continue; 43 | } else if (maze[y][x] == 'E') { 44 | return t; 45 | } else { 46 | done[y][x][b] = true; 47 | } 48 | 49 | for (int i = 0; i != 4; ++i) { 50 | int x1 = x + dx[i], y1 = y + dy[i]; 51 | if (x1 == w || y1 == h || x1 < 0 || y1 < 0) { 52 | continue; 53 | } 54 | char c = maze[y1][x1]; 55 | if (c == '#') { 56 | if (b > 0) { 57 | Node next = {x1, y1, b - 1, t + 3}; 58 | nodes.push(next); 59 | } 60 | } else { 61 | Node next = {x1, y1, b, t + 1}; 62 | nodes.push(next); 63 | } 64 | } 65 | } 66 | 67 | return -1; 68 | } 69 | -------------------------------------------------------------------------------- /D1L2/CoinMachinesGame.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int maxGames(int coins, vector need, vector give) { 7 | int n = need.size(), ret = 0; vector cost(n); 8 | for (int i = 0; i != n; ++i) { 9 | cost[i] = need[i] - give[i]; 10 | } 11 | for (int i = 0; i < n - 1; ++i) { 12 | for (int j = i + 1; j < n; ++j) { 13 | if (cost[i] > cost[j]) { 14 | swap(cost[i], cost[j]); 15 | swap(need[i], need[j]); 16 | swap(give[i], give[j]); 17 | } 18 | } 19 | } 20 | 21 | int lowest = *min_element(need.begin(), need.end()); 22 | for (int i = 0; i != n; ++i) { 23 | int avail = coins - need[i]; 24 | if (avail >= 0) { 25 | int games = 1 + (avail / cost[i]); 26 | ret += games; 27 | coins -= games * cost[i]; 28 | if (coins < lowest) { 29 | return ret; 30 | } 31 | } 32 | } 33 | return ret; 34 | } 35 | -------------------------------------------------------------------------------- /D1L2/DungeonEscape.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int h, w; 8 | int cost[50][50][4]; 9 | bool done[50][50]; 10 | 11 | int dx[] = { 0, 0, 1, -1}, 12 | dy[] = {-1, 1, 0, 0}; 13 | 14 | struct Node { 15 | int y, x, t; 16 | }; 17 | bool operator<(Node const &p, Node const &q) { 18 | return p.t > q.t; 19 | } 20 | 21 | int convert(char c) { 22 | if (c == 'x') { 23 | return -1; 24 | } 25 | return c - '0'; 26 | } 27 | 28 | int buildCost(vector const &up, 29 | vector const &down, 30 | vector const &east, 31 | vector const &west) { 32 | for (int y = 0; y != h; ++y) { 33 | for (int x = 0; x != w; ++x) { 34 | cost[y][x][0] = convert(up[y][x]); 35 | cost[y][x][1] = convert(down[y][x]); 36 | cost[y][x][2] = convert(east[y][x]); 37 | cost[y][x][3] = convert(west[y][x]); 38 | } 39 | } 40 | } 41 | 42 | int exitTime(vector const &up, 43 | vector const &down, 44 | vector const &east, 45 | vector const &west, 46 | int startLevel, 47 | int startEasting) { 48 | h = up.size(); w = up[0].size(); 49 | buildCost(up, down, east, west); 50 | memset(done, false, sizeof(done)); 51 | 52 | priority_queue nodes; 53 | Node init = {startLevel, startEasting, 0}; 54 | nodes.push(init); 55 | 56 | while (!nodes.empty()) { 57 | Node node = nodes.top(); nodes.pop(); 58 | int y = node.y, x = node.x, t = node.t; 59 | if (y < 0) { 60 | return t; 61 | } 62 | if (done[y][x]) { 63 | continue; 64 | } 65 | if (t >= w * (h - y)) { 66 | continue; 67 | } 68 | done[y][x] = true; 69 | 70 | for (int i = 0; i != 4; ++i) { 71 | int dt = cost[y][x][i]; 72 | if (dt == -1) { 73 | continue; 74 | } 75 | int y1 = y + dy[i], x1 = x + dx[i]; 76 | if (y1 >= h || x1 < 0 || x1 >= w) { 77 | continue; 78 | } 79 | int t1 = t + dt; 80 | Node next = {y1, x1, t1}; 81 | nodes.push(next); 82 | } 83 | } 84 | 85 | return -1; 86 | } 87 | -------------------------------------------------------------------------------- /D1L2/FlowerGarden.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | vector a; 8 | int beg[1001], end[1001]; 9 | 10 | bool block(int x, int y) { 11 | if (beg[x] > end[y] || beg[y] > end[x]) { 12 | return false; 13 | } 14 | return true; 15 | } 16 | 17 | vector getOrdering(vector const &height, 18 | vector const &bloom, 19 | vector const &wilt) { 20 | a = height; int n = a.size(); 21 | for (int i = 0; i != n; ++i) { 22 | beg[a[i]] = bloom[i]; 23 | end[a[i]] = wilt[i]; 24 | } 25 | 26 | sort(a.begin(), a.end(), greater()); 27 | vector ret(n); 28 | bool used[n]; memset(used, false, sizeof(used)); 29 | 30 | for (int i = 0; i != n; ++i) { 31 | for (int j = 0; j != n; ++j) { 32 | if (used[j]) { 33 | continue; 34 | } 35 | int ok = true; 36 | for (int k = j + 1; k != n; ++k) { 37 | if (!used[k] && block(a[j], a[k])) { 38 | ok = false; 39 | break; 40 | } 41 | } 42 | if (ok) { 43 | ret[i] = a[j]; 44 | used[j] = true; 45 | break; 46 | } 47 | } 48 | } 49 | 50 | return ret; 51 | } 52 | -------------------------------------------------------------------------------- /D1L2/GameEnding.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | typedef vector> Board; 6 | int dx[] = {1, 1, 2, 2, -1, -1, -2, -2}, 7 | dy[] = {2, -2, 1, -1, 2, -2, 1, -1}; 8 | int n; 9 | 10 | void put(Board &a, int y, int x) { 11 | for (int i = 0; i != n; ++i) { 12 | a[y][i] = true; 13 | a[i][x] = true; 14 | } 15 | for (int i = 0; i != 8; ++i) { 16 | int yy = y + dy[i], xx = x + dx[i]; 17 | if (yy >= 0 && yy < n && xx >= 0 && xx < n) { 18 | a[yy][xx] = true; 19 | } 20 | } 21 | } 22 | 23 | bool play(Board const &a) { 24 | for (int y = 0; y != n; ++y) { 25 | for (int x = 0; x != n; ++x) { 26 | if (!a[y][x]) { 27 | Board b = a; 28 | put(b, y, x); 29 | if (!play(b)) { 30 | return true; 31 | } 32 | } 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | string result(int N, vector const &moves) { 39 | n = N; Board a(n, vector(n, false)); 40 | for (auto move : moves) { 41 | int y = move[1] - '1', x = move[0] - 'a'; 42 | if (a[y][x]) { 43 | return "Invalid input"; 44 | } 45 | put(a, y, x); 46 | } 47 | return play(a) ^ (moves.size() % 2) ? "First player wins" 48 | : "Second player wins"; 49 | } 50 | -------------------------------------------------------------------------------- /D1L2/Jewelry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | typedef long long int64; 9 | 10 | int n, smax; 11 | vector a; 12 | int64 lo[31][30001], hi[31][30001]; 13 | vector> groups; 14 | 15 | void reverse() { 16 | for (int i = 0; i < (n/2); ++i) { 17 | swap(a[i], a[n - 1 - i]); 18 | } 19 | } 20 | 21 | int64 choose(int takes, int total) { 22 | int64 ret = 1; 23 | for (int i = 1; i <= takes; ++i) { 24 | ret *= total--; 25 | ret /= i; 26 | } 27 | return ret; 28 | } 29 | 30 | void countWays(int64 ret[31][30001]) { 31 | ret[0][0] = 1; 32 | for (int s = 1; s <= smax; ++s) { 33 | ret[0][s] = 0; 34 | } 35 | for (int i = 1; i <= n; ++i) { 36 | for (int s = 0; s <= smax; ++s) { 37 | ret[i][s] = ret[i - 1][s]; 38 | if (s >= a[i - 1]) { 39 | ret[i][s] += ret[i - 1][s - a[i - 1]]; 40 | } 41 | } 42 | } 43 | } 44 | 45 | void makeGroups() { 46 | for (int i = 1, pos = 1; i <= n; ++i) { 47 | if (i == n || a[i] != a[pos - 1]) { 48 | groups.push_back(make_pair(pos, i - pos + 1)); 49 | pos = i + 1; 50 | } 51 | } 52 | } 53 | 54 | int64 howMany(vector const &values) { 55 | a = values; n = a.size(); smax = accumulate(a.begin(), a.end(), 0); 56 | sort(a.begin(), a.end(), greater()); countWays(hi); 57 | reverse(); countWays(lo); makeGroups(); 58 | 59 | int64 ret = 0; 60 | for (int i = 0; i != groups.size(); ++i) { 61 | int pos = groups[i].first, len = groups[i].second, x = 0; 62 | for (int j = 1; j <= len; ++j) { 63 | x += a[pos - 1]; 64 | for (int s = x; s <= smax; ++s) { 65 | ret += lo[pos - 1][s - x] * 66 | hi[n - (pos + j - 1)][s] * 67 | choose(j, len); 68 | } 69 | } 70 | } 71 | return ret; 72 | } 73 | -------------------------------------------------------------------------------- /D1L2/JimmyLightning.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int N, D; 8 | int mins[50]; 9 | int vals[50]; 10 | vector> rooms; 11 | int costs[50]; 12 | int dp[50][1000]; 13 | 14 | void readDoors(vector const &doors) { 15 | N = doors.size(); 16 | mins[0] = doors[0]; 17 | for (int i = 1; i != N; ++i) { 18 | mins[i] = min(mins[i - 1], doors[i]); 19 | } 20 | } 21 | 22 | void readDiamonds(vector const &diamonds) { 23 | D = diamonds.size(); 24 | rooms.resize(N); 25 | for (int i = 0; i != D; ++i) { 26 | istringstream iss(diamonds[i]); 27 | iss >> vals[i] >> costs[i]; 28 | int room; iss >> room; 29 | rooms[room - 1].push_back(i); 30 | } 31 | } 32 | 33 | int go(int room, int t) { 34 | if (dp[room][t] != -1) { 35 | return dp[room][t]; 36 | } 37 | int ret = 0; 38 | 39 | int avail = mins[room] - t; 40 | for (auto i : rooms[room]) { 41 | if (costs[i] < avail) { 42 | ret = max(ret, vals[i] + go(room, t + costs[i])); 43 | } 44 | } 45 | if (room > 0) { 46 | ret = max(ret, go(room - 1, t)); 47 | } 48 | 49 | dp[room][t] = ret; 50 | return ret; 51 | } 52 | 53 | int robTheBank(vector const &doors, vector const &diamonds) { 54 | readDoors(doors); readDiamonds(diamonds); 55 | for (int i = 0; i != N; ++i) { 56 | for (int j = 0; j != 1000; ++j) { 57 | dp[i][j] = -1; 58 | } 59 | } 60 | return go(N - 1, 0); 61 | } 62 | -------------------------------------------------------------------------------- /D1L2/KeysInBoxes.cpp: -------------------------------------------------------------------------------- 1 | // Stirling's number of the first kind 2 | 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | typedef long long int64; 9 | 10 | int64 gcd(int64 x, int64 y) { 11 | if (y > 0) { 12 | return gcd(y, x % y); 13 | } 14 | return x; 15 | } 16 | 17 | int64 factorial(int n) { 18 | int64 ret = 1; 19 | for (int i = 2; i <= n; ++i) { 20 | ret *= i; 21 | } 22 | return ret; 23 | } 24 | 25 | string getAllKeys(int N, int M) { 26 | vector> a; 27 | a.assign(N + 1, vector(M + 1, 0)); 28 | a[1][1] = 1; 29 | for (int n = 2; n <= N; ++n) { 30 | for (int m = 1; m <= M; ++m) { 31 | a[n][m] = a[n - 1][m - 1] + (n - 1) * a[n - 1][m]; 32 | } 33 | } 34 | 35 | int64 p = 0; 36 | for (int m = 1; m <= M; ++m) { 37 | p += a[N][m]; 38 | } 39 | int64 q = factorial(N); 40 | 41 | int64 d = gcd(p, q); 42 | p /= d; 43 | q /= d; 44 | 45 | ostringstream oss; 46 | oss << p << '/' << q; 47 | return oss.str(); 48 | } 49 | -------------------------------------------------------------------------------- /D1L2/OddsAndEvens.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | void parse(vector const &a, int &evens, int &odds) { 8 | for (auto elem : a) { 9 | if (elem == "EVEN") { 10 | ++evens; 11 | } else { 12 | ++odds; 13 | } 14 | } 15 | } 16 | 17 | /* 18 | x evens, y odds 19 | sE even sums, sO odd sums 20 | pE even sums, pO odd sums 21 | Then: 22 | x(x - 1)/2 + y(y - 1)/2 = sE 23 | xy = sO 24 | y(y - 1)/2 = pO 25 | xy + x(x - 1)/2 = pE 26 | */ 27 | 28 | int equation(int a) { 29 | return (1 + floor(sqrt((double) (8 * a + 1)))) / 2; 30 | } 31 | 32 | bool solve(int sE, int sO, int pE, int pO, int &x, int &y) { 33 | if (pO == 0) { 34 | if (sO == 0) { 35 | y = 0; x = equation(sE); 36 | } else { 37 | y = 1; x = sO; 38 | } 39 | } else { 40 | y = equation(pO); x = sO / y; 41 | } 42 | return x * y == sO && 43 | y * (y - 1) / 2 == pO && 44 | x * (x - 1) / 2 == sE - pO && 45 | sE - pO == pE - sO; 46 | } 47 | 48 | string find(vector const &sums, vector const &products) { 49 | int sE = 0, sO = 0, pE = 0, pO = 0; 50 | parse(sums, sE, sO); 51 | parse(products, pE, pO); 52 | 53 | int x, y; 54 | if (!solve(sE, sO, pE, pO, x, y)) { 55 | return "IMPOSSIBLE"; 56 | } 57 | 58 | ostringstream oss; 59 | oss << "EVEN " << x << " ODD " << y; 60 | return oss.str(); 61 | } 62 | -------------------------------------------------------------------------------- /D1L2/Paths.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int INF = 1000; 7 | vector a; 8 | int n, b[50], c[50]; 9 | 10 | void dfs(int x, int cost) { 11 | if (cost >= c[x] || cost == b[x]) { 12 | return; 13 | } 14 | 15 | if (cost < b[x]) { 16 | c[x] = b[x]; 17 | b[x] = cost; 18 | } else { 19 | c[x] = cost; 20 | } 21 | 22 | for (int i = 0; i != n; ++i) { 23 | if (a[x][i] != 'X') { 24 | dfs(i, cost + a[x][i] - '0'); 25 | } 26 | } 27 | } 28 | 29 | int secondBest(vector const &graph, int from, int to) { 30 | a = graph; n = a.size(); 31 | fill(b, b + n, INF); 32 | fill(c, c + n, INF); 33 | 34 | dfs(from, 0); 35 | return c[to] == INF ? -1 : c[to]; 36 | } 37 | -------------------------------------------------------------------------------- /D1L2/ReversalChain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int INF = 51; 7 | const int NEW = -2; 8 | string a, b; 9 | int memo[51][50][50][2]; 10 | 11 | int go(int n, int i, int j, bool k) { 12 | if (memo[n][i][j][k] != NEW) { 13 | return memo[n][i][j][k]; 14 | } 15 | int ret = INF; 16 | 17 | if (k == 0) { 18 | if (a[i] == b[j]) { 19 | ret = min(ret, go(n - 1, i + 1, j + 1, 0)); 20 | } 21 | if (a[i + n - 1] == b[j + n - 1]) { 22 | ret = min(ret, go(n - 1, i, j, 0)); 23 | } 24 | if (a[i] == b[j + n - 1]) { 25 | ret = min(ret, go(n - 1, i + 1, j, 1) + 1); 26 | } 27 | if (a[i + n - 1] == b[j]) { 28 | ret = min(ret, go(n - 1, i, j + 1, 1) + 1); 29 | } 30 | } else { 31 | if (a[i] == b[j]) { 32 | ret = min(ret, go(n - 1, i + 1, j + 1, 0) + 1); 33 | } 34 | if (a[i + n - 1] == b[j + n - 1]) { 35 | ret = min(ret, go(n - 1, i, j, 0) + 1); 36 | } 37 | if (a[i] == b[j + n - 1]) { 38 | ret = min(ret, go(n - 1, i + 1, j, 1)); 39 | } 40 | if (a[i + n - 1] == b[j]) { 41 | ret = min(ret, go(n - 1, i, j + 1, 1)); 42 | } 43 | } 44 | 45 | memo[n][i][j][k] = ret; 46 | return ret; 47 | } 48 | 49 | int minReversal(string const &init, string const &goal) { 50 | a = init; b = goal; 51 | int n = a.size(); 52 | for (int i = 0; i != n; ++i) { 53 | for (int j = 0; j != n; ++j) { 54 | memo[0][i][j][0] = 0; 55 | memo[0][i][j][1] = 0; 56 | for (int len = 1; len <= n; ++len) { 57 | memo[len][i][j][0] = NEW; 58 | memo[len][i][j][1] = NEW; 59 | } 60 | } 61 | } 62 | int ret = go(n, 0, 0, 0); 63 | return ret == INF ? -1 : ret; 64 | } 65 | -------------------------------------------------------------------------------- /D1L2/Rumor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int n; 7 | bool can[16][16]; 8 | vector init; 9 | 10 | void readKnowledge(string const &knowledge) { 11 | int know = 0; 12 | for (int i = 0; i != n; ++i) { 13 | if (knowledge[i] == 'Y') { 14 | know |= (1 << i); 15 | } 16 | } 17 | init = {know, know}; 18 | } 19 | 20 | void readGraph(vector const &graph) { 21 | for (int i = 0; i != n; ++i) { 22 | for (int j = 0; j != n; ++j) { 23 | can[i][j] = graph[i][j] == 'Y'; 24 | } 25 | } 26 | } 27 | 28 | void spread(int rabbit, int &know) { 29 | for (int i = 0; i != n; ++i) { 30 | if (can[rabbit][i]) { 31 | know |= (1 << i); 32 | } 33 | } 34 | } 35 | 36 | bool filled(vector const &a) { 37 | return (a[0] == (1 << n) - 1) 38 | && (a[1] == (1 << n) - 1); 39 | } 40 | 41 | int getMinimum(string const &knowledge, vector const &graph) { 42 | n = knowledge.size(); 43 | readKnowledge(knowledge); 44 | readGraph(graph); 45 | 46 | int best = 100; 47 | 48 | for (int order = 0; order < (1 << n); ++order) { 49 | auto a(init); 50 | int once = 0, twice = 0; 51 | 52 | for (int day = 0; day < best; ++day) { 53 | if (filled(a)) { 54 | best = min(best, day); 55 | break; 56 | } 57 | 58 | auto b(a); 59 | 60 | for (int i = 0; i != n; ++i) { 61 | int bit = 1 << i; 62 | if (twice & bit) { 63 | continue; 64 | } 65 | 66 | bool rumor = ((order & bit) > 0) ^ ((once & bit) > 0); 67 | if (a[rumor] & bit) { 68 | spread(i, b[rumor]); 69 | if (once & bit) { 70 | twice |= bit; 71 | } else { 72 | once |= bit; 73 | } 74 | } 75 | } 76 | 77 | if (a[0] == b[0] && a[1] == b[1]) { 78 | break; 79 | } 80 | a = b; 81 | } 82 | } 83 | 84 | return best == 100 ? -1 : best; 85 | } 86 | -------------------------------------------------------------------------------- /D1L2/StripePainter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | vector a; 7 | int dp[51][51][27]; 8 | 9 | void compress(string const &s, vector &ret) { 10 | ret.push_back(s[0] - 'A'); 11 | for (int i = 1; i < s.size(); ++i) { 12 | if (s[i] != s[i - 1]) { 13 | ret.push_back(s[i] - 'A'); 14 | } 15 | } 16 | } 17 | 18 | void init() { 19 | for (int lo = 0; lo != 51; ++lo) { 20 | for (int hi = 0; hi != 51; ++hi) { 21 | for (int val = 0; val != 27; ++val) { 22 | dp[lo][hi][val] = lo > hi ? 0 : -1; 23 | } 24 | } 25 | } 26 | } 27 | 28 | int cost(int lo, int hi, int cur) { 29 | if (dp[lo][hi][cur] != -1) { 30 | return dp[lo][hi][cur]; 31 | } 32 | int ret; 33 | if (a[lo] == cur) { 34 | ret = cost(lo + 1, hi, cur); 35 | } else { 36 | ret = 51; 37 | for (int mid = lo; mid <= hi; ++mid) { 38 | if (a[mid] == a[lo]) { 39 | ret = min(ret, cost(lo, mid, a[lo]) + cost(mid + 1, hi, cur)); 40 | } 41 | } 42 | ++ret; 43 | } 44 | dp[lo][hi][cur] = ret; 45 | return ret; 46 | } 47 | 48 | int minStrokes(string const &stripes) { 49 | compress(stripes, a); 50 | init(); 51 | return cost(0, a.size() - 1, 26); // Apparently 26 is a very ugly color 52 | } -------------------------------------------------------------------------------- /D1L3/IslandFerries.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int F, L; 10 | bool edge[10][40][40]; 11 | int cost[10][40]; 12 | bool done[40][1 << 10]; 13 | int reachable; 14 | 15 | struct Node { 16 | int at; 17 | int spent; 18 | int has; 19 | }; 20 | bool operator<(Node const &p, Node const &q) { 21 | return p.spent > q.spent; 22 | } 23 | 24 | int countBits(int mask) { 25 | int ret = 0; 26 | while (mask != 0) { 27 | ret += (mask & 1); 28 | mask >>= 1; 29 | } 30 | return ret; 31 | } 32 | 33 | void getLegs(vector const &legs) { 34 | F = legs.size(); 35 | memset(edge, false, sizeof(edge)); 36 | bool canReach[40]; memset(canReach, false, sizeof(canReach)); 37 | for (int f = 0; f != F; ++f) { 38 | istringstream iss(legs[f]); 39 | while (true) { 40 | int src, dst; 41 | iss >> src; 42 | if (!iss.good()) { 43 | break; 44 | } 45 | iss.ignore(1); 46 | iss >> dst; 47 | edge[f][src][dst] = true; 48 | canReach[dst] = true; 49 | } 50 | } 51 | 52 | reachable = 0; 53 | for (int i = 0; i != 40; ++i) { 54 | if (canReach[i]) { 55 | ++reachable; 56 | } 57 | } 58 | } 59 | 60 | void getPrices(vector const &prices) { 61 | L = prices.size(); 62 | for (int l = 0; l != L; ++l) { 63 | istringstream iss(prices[l]); 64 | for (int f = 0; f != F; ++f) { 65 | iss >> cost[f][l]; 66 | } 67 | } 68 | } 69 | 70 | vector costs(vector const &legs, 71 | vector const &prices) { 72 | getLegs(legs); 73 | getPrices(prices); 74 | vector ret(L - 1, -1); 75 | 76 | priority_queue nodes; 77 | Node init = {0, 0, 0}; 78 | nodes.push(init); 79 | 80 | memset(done, false, sizeof(done)); 81 | int found = 0; 82 | 83 | while (!nodes.empty()) { 84 | Node node = nodes.top(); nodes.pop(); 85 | int at = node.at, spent = node.spent, has = node.has; 86 | 87 | if (at != 0) { 88 | if (ret[at - 1] == -1) { 89 | ret[at - 1] = spent; 90 | if (++found == reachable) { 91 | break; 92 | } 93 | } 94 | } 95 | 96 | if (done[at][has]) { 97 | continue; 98 | } 99 | done[at][has] = true; 100 | 101 | if (has != 0) { 102 | for (int to = 0; to != L; ++to) { 103 | if (to == at) { 104 | continue; 105 | } 106 | for (int f = 0; f != F; ++f) { 107 | if ((has & (1 << f)) && edge[f][at][to]) { 108 | Node next = {to, spent, (has ^ (1 << f))}; 109 | nodes.push(next); 110 | } 111 | } 112 | } 113 | } 114 | 115 | if (countBits(has) < 3) { 116 | for (int f = 0; f != F; ++f) { 117 | if ((has & (1 << f)) == 0) { 118 | Node next = {at, spent + cost[f][at], (has | (1 << f))}; 119 | nodes.push(next); 120 | } 121 | } 122 | } 123 | } 124 | 125 | return ret; 126 | } 127 | -------------------------------------------------------------------------------- /D1L3/KiloManX.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct Node { 8 | int state; 9 | int shots; 10 | Node(int state, int shots) : state(state), shots(shots) { } 11 | }; 12 | 13 | bool operator<(Node const& left, Node const &right) { 14 | return left.shots > right.shots; 15 | } 16 | 17 | int leastShots(vector const &weapons, 18 | vector const &bosses) { 19 | int n = weapons.size(), m = 1 << n; 20 | bool done[m]; fill(done, done + m, false); --m; 21 | 22 | priority_queue nodes; 23 | nodes.push(Node(0, 0)); 24 | 25 | while (!nodes.empty()) { 26 | Node node = nodes.top(); nodes.pop(); 27 | 28 | int state = node.state, shots = node.shots; 29 | if (done[state]) { 30 | continue; 31 | } 32 | done[state] = true; 33 | 34 | if (state == m) { 35 | return shots; 36 | } 37 | 38 | for (int boss = 0; boss != n; ++boss) { 39 | if ((state >> boss) & 1) { 40 | continue; 41 | } 42 | 43 | int best = 1; 44 | for (int weapon = 0; weapon != n; ++weapon) { 45 | if (weapon == boss) { 46 | continue; 47 | } 48 | if (((state >> weapon) & 1) == 0) { 49 | continue; 50 | } 51 | int damage = weapons[weapon][boss] - '0'; 52 | best = max(best, damage); 53 | } 54 | 55 | int newState = state | (1 << boss); 56 | 57 | int health = bosses[boss]; 58 | int newShots = shots + (health / best); 59 | if (health % best != 0) { 60 | ++newShots; 61 | } 62 | 63 | nodes.push(Node(newState, newShots)); 64 | } 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /D1L3/RoboCourier.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | bool edges[1001][1001][6]; 9 | bool done[1001][1001][6]; 10 | int dx[] = {0, 1, 1, 0, -1, -1}, 11 | dy[] = {1, 0, -1, -1, 0, 1}; 12 | int endx, endy; 13 | 14 | struct Node { 15 | int x, y, t, dir, acc; 16 | }; 17 | bool operator<(Node const& p, Node const &q) { 18 | if (p.t == q.t) return p.acc < q.acc; 19 | return p.t > q.t; 20 | } 21 | 22 | void buildGraph(vector const &path) { 23 | int dir = 0, x = 500, y = 500; 24 | for (int i = 0; i != path.size(); ++i) { 25 | for (int j = 0; j != path[i].size(); ++j) { 26 | switch (path[i][j]) { 27 | case 'L': dir = (dir + 5) % 6; break; 28 | case 'R': dir = (dir + 1) % 6; break; 29 | case 'F': edges[x][y][dir] = true; 30 | x += dx[dir]; y += dy[dir]; 31 | edges[x][y][(dir + 3) % 6] = true; 32 | } 33 | } 34 | } 35 | endx = x; endy = y; 36 | } 37 | 38 | int timeToDeliver(vector const &path) { 39 | memset(edges, false, sizeof(edges)); 40 | memset(done, false, sizeof(done)); 41 | buildGraph(path); 42 | 43 | priority_queue nodes; 44 | Node init = {500, 500, 0, 0, 0}; 45 | nodes.push(init); 46 | 47 | while (!nodes.empty()) { 48 | Node node = nodes.top(); nodes.pop(); 49 | int x = node.x, y = node.y, t = node.t, dir = node.dir, acc = node.acc; 50 | if (x == endx && y == endy) { 51 | return t; 52 | } else if (done[x][y][dir]) { 53 | continue; 54 | } else { 55 | done[x][y][dir] = true; 56 | } 57 | 58 | for (int i = 0; i != 6; ++i) { 59 | if (!edges[x][y][i]) { 60 | continue; 61 | } 62 | 63 | int x1 = x + dx[i], y1 = y + dy[i], t1, acc1; 64 | if (i == dir) { 65 | t1 = t + ((acc >= 2) ? 2 : 4); 66 | acc1 = acc + 1; 67 | } else { 68 | int pivot = min((i + 6 - dir) % 6, (dir + 6 - i) % 6); 69 | t1 = t + 3 * pivot + 4; 70 | acc1 = 1; 71 | } 72 | 73 | Node next = {x1, y1, t1, i, acc1}; 74 | nodes.push(next); 75 | } 76 | } 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /D1L3/RookAttack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int h, w; 11 | vector> graph; 12 | vector row; // row[i] -> the column that currently matches row i 13 | vector col; // col[i] -> the row that currently matches column i 14 | 15 | bool findPath(int y0) { 16 | map prev; prev[y0] = y0; 17 | queue ys; ys.push(y0); 18 | while (!ys.empty()) { 19 | int y = ys.front(); ys.pop(); 20 | for (int x : graph[y]) { 21 | int y1 = col[x]; 22 | if (y1 == y) { 23 | continue; 24 | } 25 | if (y1 == -1) { 26 | while (y != y0) { 27 | int oldx = row[y]; 28 | row[y] = x; col[x] = y; 29 | y = prev[y]; x = oldx; 30 | } 31 | row[y0] = x; col[x] = y0; 32 | return true; 33 | } 34 | if (prev.find(y1) == prev.end()) { 35 | ys.push(y1); 36 | prev[y1] = y; 37 | } 38 | } 39 | } 40 | return false; 41 | } 42 | 43 | set> parseCuts(vector const &cutouts) { 44 | set> ret; 45 | for (auto cutout : cutouts) { 46 | istringstream iss(cutout); 47 | while (true) { 48 | int y, x; iss >> y >> x; 49 | ret.insert(make_pair(y, x)); 50 | if (iss.eof()) { 51 | break; 52 | } 53 | iss.ignore(1); 54 | } 55 | } 56 | return ret; 57 | } 58 | 59 | void buildGraph(set> const &cuts) { 60 | graph.assign(h, {}); 61 | for (int y = 0; y != h; ++y) { 62 | for (int x = 0; x != w; ++x) { 63 | if (cuts.find(make_pair(y, x)) == cuts.end()) { 64 | graph[y].push_back(x); 65 | } 66 | } 67 | } 68 | } 69 | 70 | int howMany(int rows, int cols, vector const &cutouts) { 71 | h = rows; w = cols; buildGraph(parseCuts(cutouts)); 72 | row.assign(h, -1); col.assign(w, -1); 73 | 74 | int ret = 0; 75 | for (int y = 0; y != h; ++y) { 76 | ret += findPath(y); 77 | } 78 | return ret; 79 | } 80 | -------------------------------------------------------------------------------- /D2L1/Archery.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | double expectedPoints(int N, vector const &ringPoints) { 5 | double ret = 0; 6 | for (int i = 0; i <= N; ++i) { 7 | ret += (2 * i + 1) * ringPoints[i]; 8 | } 9 | return ret /= ((N + 1) * (N + 1)); 10 | } 11 | -------------------------------------------------------------------------------- /D2L1/BishopMove.go: -------------------------------------------------------------------------------- 1 | package BishopMove 2 | 3 | func HowManyMoves(r1 int, c1 int, r2 int, c2 int) int { 4 | switch { 5 | case r2 == r1 && c2 == c1: 6 | return 0 7 | case (r2 - r1 == c2 - c1) || (r2 - r1 == c1 - c2): 8 | return 1 9 | case (r1 + c1) % 2 != (r2 + c2) % 2: 10 | return -1 11 | } 12 | return 2 13 | } -------------------------------------------------------------------------------- /D2L1/BishopMove.py: -------------------------------------------------------------------------------- 1 | def howManyMoves(r1, c1, r2, c2): 2 | if r2 == r1 and c2 == c1: 3 | return 0 4 | if abs(r2 - r1) == abs(c2 - c1): 5 | return 1 6 | if (r1 + c1) % 2 != (r2 + c2) % 2: 7 | return -1 8 | return 2 9 | -------------------------------------------------------------------------------- /D2L1/BlackAndWhiteSolitaire.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int count(string const &cards, bool start) { 6 | int ret = 0; 7 | for (auto card : cards) { 8 | ret += ((card == 'B') ^ start); 9 | start = !start; 10 | } 11 | return ret; 12 | } 13 | 14 | int minimumTurns(string const &cards) { 15 | return min(count(cards, true), count(cards, false)); 16 | } 17 | -------------------------------------------------------------------------------- /D2L1/Chopsticks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int getmax(vector const &length) { 5 | vector a(101, 0); 6 | for (auto x : length) { 7 | ++a[x]; 8 | } 9 | 10 | int ret = 0; 11 | for (int i = 1; i <= 100; ++i) { 12 | ret += (a[i] / 2); 13 | } 14 | 15 | return ret; 16 | } 17 | -------------------------------------------------------------------------------- /D2L1/ClockWalk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int finalPosition(string const &flips) { 6 | int ret = 0; 7 | for (int i = 0; i != flips.size(); ++i) { 8 | if (flips[i] == 'h') { 9 | ret = (ret + i + 1) % 12; 10 | } else { 11 | ret = (ret + 59 - i) % 12; 12 | } 13 | } 14 | return ret == 0 ? 12 : ret; 15 | } 16 | -------------------------------------------------------------------------------- /D2L1/DietPlan.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int toMask(string const &s) { 7 | int ret = 0; 8 | for (auto c : s) { 9 | ret |= (1 << (c - 'A')); 10 | } 11 | return ret; 12 | } 13 | 14 | string toString(int mask) { 15 | ostringstream oss; 16 | for (int i = 0; mask; ++i) { 17 | if (mask & 1) { 18 | oss.put(i + 'A'); 19 | } 20 | mask >>= 1; 21 | } 22 | return oss.str(); 23 | } 24 | 25 | string chooseDinner(string const &diet, 26 | string const &breakfast, 27 | string const &lunch) { 28 | int x = toMask(diet); 29 | int y = toMask(breakfast) | toMask(lunch); 30 | int ret = x ^ y; 31 | return (ret & x) == ret ? toString(ret) : "CHEATER"; 32 | } 33 | -------------------------------------------------------------------------------- /D2L1/DigitHoles.cpp: -------------------------------------------------------------------------------- 1 | int numHoles(int number) { 2 | static int holes[] = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1}; 3 | int ret = 0; 4 | while (number > 0) { 5 | ret += holes[number%10]; 6 | number/=10; 7 | } 8 | return ret; 9 | } 10 | -------------------------------------------------------------------------------- /D2L1/DigitHoles.hs: -------------------------------------------------------------------------------- 1 | module DigitHoles where 2 | 3 | hole :: Int -> Int 4 | hole 0 = 1 5 | hole 4 = 1 6 | hole 6 = 1 7 | hole 8 = 2 8 | hole 9 = 1 9 | hole _ = 0 10 | 11 | numHoles :: Int -> Int 12 | numHoles 0 = 0 13 | numHoles n = hole (mod n 10) + numHoles (div n 10) 14 | -------------------------------------------------------------------------------- /D2L1/DigitHoles.java: -------------------------------------------------------------------------------- 1 | public class DigitHoles { 2 | public int numHoles(int number) { 3 | String s = Integer.toString(number); 4 | int ret = 0; 5 | for (int i = 0; i < s.length(); ++i) { 6 | switch (s.charAt(i) - '0') { 7 | case 0: 8 | case 4: 9 | case 6: 10 | case 9: 11 | ret += 1; 12 | break; 13 | case 8: 14 | ret += 2; 15 | break; 16 | } 17 | } 18 | return ret; 19 | } 20 | } -------------------------------------------------------------------------------- /D2L1/DinkyFish.cpp: -------------------------------------------------------------------------------- 1 | int monthsUntilCrowded(int volume, int males, int females) { 2 | int lim = 2 * volume, ret = 0, more = males < females ? males : females; 3 | for (int pop = males + females; pop <= lim; pop += more * (1 << ret)) { 4 | ++ret; 5 | } 6 | return ret; 7 | } 8 | -------------------------------------------------------------------------------- /D2L1/DitherCounter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int count(string const &dithered, vector const &screen) { 7 | bool a[26]; fill(a, a + 26, false); 8 | for (auto c : dithered) { 9 | a[c - 'A'] = true; 10 | } 11 | int ret = 0; 12 | for (auto line : screen) { 13 | for (auto c : line) { 14 | ret += a[c - 'A']; 15 | } 16 | } 17 | return ret; 18 | } 19 | -------------------------------------------------------------------------------- /D2L1/EasyHomework.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | string determineSign(vector const &a) { 6 | bool pos = true; 7 | for (auto n : a) { 8 | if (n == 0) { 9 | return "ZERO"; 10 | } else if (n < 0) { 11 | pos = !pos; 12 | } 13 | } 14 | return pos ? "POSITIVE" : "NEGATIVE"; 15 | } 16 | -------------------------------------------------------------------------------- /D2L1/FilipTheFrog.js: -------------------------------------------------------------------------------- 1 | exports.countReachableIslands = function(a, L) { 2 | var n = a.length; 3 | var i; 4 | 5 | var start = a[0]; 6 | a.sort(function (x, y) { 7 | return x - y; 8 | }); 9 | var k = 0; 10 | for (i = 0; i < n; ++i) { 11 | if (a[i] == start) { 12 | k = i; 13 | break; 14 | } 15 | } 16 | 17 | var ret = 1; 18 | for (i = k; i > 0 && a[i] - L <= a[i - 1]; --i) { 19 | ret++; 20 | } 21 | for (i = k; i < (n - 1) && a[i] + L >= a[i + 1]; ++i) { 22 | ret++; 23 | } 24 | return ret; 25 | }; 26 | -------------------------------------------------------------------------------- /D2L1/GardenHose.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int countDead(int n, int row, int col, int hose) { 5 | int y = max(0, n - (hose/row) * 2); 6 | int x = max(0, n - (hose/col) * 2); 7 | return y * x; 8 | } 9 | -------------------------------------------------------------------------------- /D2L1/IncredibleMachineEasy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | double gravitationalAcceleration(vector const &height, 6 | int T) { 7 | double sum = 0; 8 | for (int i = 0; i != height.size(); ++i) 9 | sum += sqrt(height[i]); 10 | double t = T/sum; 11 | return 2/(t*t); 12 | } 13 | -------------------------------------------------------------------------------- /D2L1/IncredibleMachineEasy.hs: -------------------------------------------------------------------------------- 1 | module IncredibleMachineEasy where 2 | 3 | gravitationalAcceleration :: [Int] -> Int -> Double 4 | gravitationalAcceleration height t = 2/(x*x) 5 | where x = (fromIntegral t)/s 6 | s = sum . (map $ sqrt . fromIntegral) $ height 7 | -------------------------------------------------------------------------------- /D2L1/IncredibleMachineEasy.java: -------------------------------------------------------------------------------- 1 | public class IncredibleMachineEasy { 2 | public double gravitationalAcceleration(int[] height, 3 | int T) { 4 | double sum = 0; 5 | for (int i = 0; i < height.length; ++i) { 6 | sum += Math.sqrt(2 * height[i]); 7 | } 8 | double ret = sum / T; 9 | return ret * ret; 10 | } 11 | } -------------------------------------------------------------------------------- /D2L1/InfiniteString.rb: -------------------------------------------------------------------------------- 1 | class InfiniteString 2 | def equal(s, t) 3 | ls, lt = s.size, t.size 4 | n = ls.lcm(lt) 5 | ss = s * (n / ls) 6 | tt = t * (n / lt) 7 | return ss == tt ? "Equal" : "Not equal" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /D2L1/MostCommonLetters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | string listMostCommon(vector const &text) { 8 | int a[26]; 9 | fill(begin(a), end(a), 0); 10 | for (auto s : text) { 11 | for (auto c : s) { 12 | int i = c - 'a'; 13 | if (i >= 0 && i < 26) { 14 | ++a[i]; 15 | } 16 | } 17 | } 18 | 19 | int max = *max_element(begin(a), end(a)); 20 | ostringstream oss; 21 | for (int i = 0; i != 26; ++i) { 22 | if (a[i] == max) { 23 | oss.put(i + 'a'); 24 | } 25 | } 26 | return oss.str(); 27 | } 28 | -------------------------------------------------------------------------------- /D2L1/NinjaTurtles.cpp: -------------------------------------------------------------------------------- 1 | int countOpponents(int P, int K) { 2 | int lower = 3 * K * P / (K + 9); 3 | int upper = 3 * K * (P + 4) / (K + 9); 4 | for (int N = lower; N <= upper; ++N) { 5 | if (3 * (N / K) + N / 3 == P) { 6 | return N; 7 | } 8 | } 9 | return -1; 10 | } 11 | -------------------------------------------------------------------------------- /D2L1/OnLineRank.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int calcRanks(int k, vector const &scores) { 7 | int n = scores.size(), ret = n; 8 | for (int i = 0; i != n; ++i) { 9 | for (int j = i - 1; j >= max(i - k, 0); --j) { 10 | ret += (scores[i] < scores[j]); 11 | } 12 | } 13 | return ret; 14 | } 15 | -------------------------------------------------------------------------------- /D2L1/PaperRockScisQuals.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int frame(char x, char y) { 6 | if (x == y) { 7 | return 0; 8 | } 9 | switch (x) { 10 | case 'P': return y == 'R' ? 1 : -1; 11 | case 'R': return y == 'S' ? 1 : -1; 12 | case 'S': return y == 'P' ? 1 : -1; 13 | } 14 | } 15 | 16 | int game(string const &xs, string const &ys) { 17 | int px = 0, py = 0; 18 | for (int i = 0; i != 5; ++i) { 19 | switch (frame(xs[i], ys[i])) { 20 | case 1: ++px; break; 21 | case -1: ++py; break; 22 | } 23 | } 24 | if (px == py) { 25 | return 0; 26 | } 27 | return px > py ? 1 : -1; 28 | } 29 | 30 | int whoPassed(vector const &a) { 31 | int n = a.size(); 32 | vector p(n, 0); 33 | 34 | for (int i = 0; i < n - 1; ++i) { 35 | for (int j = i + 1; j < n; ++j) { 36 | switch (game(a[i], a[j])) { 37 | case 1: p[i] += 2; break; 38 | case 0: p[i]++; p[j]++; break; 39 | case -1: p[j] += 2; 40 | } 41 | } 42 | } 43 | 44 | int ret = 0; 45 | for (int i = 1; i < n; ++i) { 46 | if (p[i] > p[ret]) { 47 | ret = i; 48 | } 49 | } 50 | return ret; 51 | } 52 | -------------------------------------------------------------------------------- /D2L1/RainyRoad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | string isReachable(vector const &road) { 6 | static const string NO = "NO"; 7 | static const string YES = "YES"; 8 | 9 | int n = road[0].size(); 10 | for (int i = 1; i != n; ++i) { 11 | if (road[0][i] == 'W' && road[1][i] == 'W') { 12 | return NO; 13 | } 14 | } 15 | return YES; 16 | } 17 | -------------------------------------------------------------------------------- /D2L1/RainyRoad.hs: -------------------------------------------------------------------------------- 1 | module RainyRoad where 2 | 3 | toString :: Bool -> String 4 | toString False = "NO" 5 | toString True = "YES" 6 | 7 | passable :: (Char, Char) -> Bool 8 | passable ('W', 'W') = False 9 | passable _ = True 10 | 11 | isReachable :: [String] -> String 12 | isReachable road = toString $ all passable $ zip (road!!0) (road!!1) 13 | -------------------------------------------------------------------------------- /D2L1/RedAndGreen.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int minPaints(string const &row) { 7 | int n = row.size(), best = 0, reds = 0; 8 | for (int i = n - 1; i >= 0; --i) { 9 | switch (row[i]) { 10 | case 'R': 11 | ++reds; 12 | break; 13 | case 'G': 14 | best = min(best + 1, reds); 15 | } 16 | } 17 | return best; 18 | } 19 | -------------------------------------------------------------------------------- /D2L1/RedAndGreen.hs: -------------------------------------------------------------------------------- 1 | module RedAndGreen where 2 | 3 | best :: String -> Int -> Int 4 | best [] _ = 0 5 | best ('R':xs) reds = best xs (reds - 1) 6 | best ('G':xs) reds = min (1 + (best xs reds)) reds 7 | 8 | minPaints :: String -> Int 9 | minPaints row = best row (length $ filter (== 'R') row) 10 | -------------------------------------------------------------------------------- /D2L1/Reppity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int longestRep(string const &input) { 7 | int n = input.size(); 8 | auto pb = begin(input), pe = end(input); 9 | 10 | for (int len = n/2; len > 0; --len) { 11 | for (auto p = pb; p <= pb + input.size() - 2*len; ++p) { 12 | if (search(p + len, pe, p, p + len) != pe) { 13 | return len; 14 | } 15 | } 16 | } 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /D2L1/SRMCards.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int maxTurns(vector const &cards) { 5 | bool a[502]; 6 | fill(a, a + 502, false); 7 | 8 | for (int i = 0; i < cards.size(); ++i) 9 | a[cards[i]] = true; 10 | 11 | int ret = 0; 12 | for (int i = 1; i <= 500; ++i) 13 | if (a[i]) { 14 | if (a[i + 1]) ++i; 15 | ++ret; 16 | } 17 | 18 | return ret; 19 | } 20 | -------------------------------------------------------------------------------- /D2L1/SRMCards.hs: -------------------------------------------------------------------------------- 1 | module SRMCards where 2 | 3 | import Data.List 4 | 5 | maxTurns' :: [Int] -> Int 6 | maxTurns' [] = 0 7 | maxTurns' [x] = 1 8 | maxTurns' (x:y:ys) | x == y - 1 = 1 + maxTurns' ys 9 | | otherwise = 1 + maxTurns' (y:ys) 10 | 11 | maxTurns :: [Int] -> Int 12 | maxTurns cards = maxTurns' (sort cards) 13 | -------------------------------------------------------------------------------- /D2L1/SRMCards.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class SRMCards { 4 | public int maxTurns(int[] cards) { 5 | Arrays.sort(cards); 6 | int ret = 0, prev = 0; 7 | for (int i = 0; i < cards.length; ++i) { 8 | if (cards[i] != prev) { 9 | ++ret; 10 | prev = cards[i] + 1; 11 | } 12 | } 13 | return ret; 14 | } 15 | } -------------------------------------------------------------------------------- /D2L1/SRMRoomAssignmentPhase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | bool gt(int x, int y) { 7 | return x > y; 8 | } 9 | 10 | int countCompetitors(vector a, int k) { 11 | int x = a[0], ret = 0; 12 | sort(a.begin(), a.end(), gt); 13 | int p = (find(a.begin(), a.end(), x) - a.begin()) % k; 14 | for (int i = p; i < a.size(); i += k) { 15 | if (a[i] > x) { 16 | ++ret; 17 | } 18 | } 19 | return ret; 20 | } 21 | -------------------------------------------------------------------------------- /D2L1/SRMRoomAssignmentPhase.hs: -------------------------------------------------------------------------------- 1 | module SRMRoomAssignmentPhase where 2 | 3 | import Data.List 4 | import Data.Array 5 | 6 | count :: Array Int Int -> [Int] -> Int -> Int 7 | count a is x = length $ filter (> x) $ map (a!) is 8 | 9 | countCompetitors :: [Int] -> Int -> Int 10 | countCompetitors ratings k = 11 | case findIndex (== x) sorted of 12 | Just p -> count a (takeWhile (< n) (iterate (+k) (mod p k))) x 13 | Nothing -> -1 14 | where sorted = sortBy (flip compare) ratings 15 | n = length ratings 16 | x = head ratings 17 | a = listArray (0, n - 1) sorted 18 | -------------------------------------------------------------------------------- /D2L1/Segments.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | void normalise(vector &s) { 6 | if (s[0] > s[2]) { 7 | swap(s[0], s[2]); 8 | } 9 | if (s[1] > s[3]) { 10 | swap(s[1], s[3]); 11 | } 12 | } 13 | 14 | string intersection(vector s1, vector s2) { 15 | normalise(s1); normalise(s2); 16 | int x1 = max(s1[0], s2[0]), 17 | x2 = min(s1[2], s2[2]), 18 | y1 = max(s1[1], s2[1]), 19 | y2 = min(s1[3], s2[3]); 20 | if (x1 > x2 || y1 > y2) { 21 | return "NO"; 22 | } 23 | if (x1 == x2 && y1 == y2) { 24 | return "POINT"; 25 | } 26 | return "SEGMENT"; 27 | } 28 | -------------------------------------------------------------------------------- /D2L1/SerialNumbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | enum Ordering { 7 | LT, 8 | EQ, 9 | GT 10 | }; 11 | 12 | template 13 | Ordering compare(T const &x, T const &y) { 14 | if (x < y) { 15 | return LT; 16 | } else if (x > y) { 17 | return GT; 18 | } else { 19 | return EQ; 20 | } 21 | } 22 | 23 | int sumDigits(string const &x) { 24 | int ret = 0; 25 | for (auto c : x) { 26 | if (c >= '0' && c <= '9') { 27 | ret += c - '0'; 28 | } 29 | } 30 | return ret; 31 | } 32 | 33 | bool compareSerials(string const &x, string const &y) { 34 | switch (compare(x.size(), y.size())) { 35 | case LT: return true; 36 | case GT: return false; 37 | case EQ: 38 | switch (compare(sumDigits(x), sumDigits(y))) { 39 | case LT: return true; 40 | case GT: return false; 41 | case EQ: return x < y; 42 | } 43 | } 44 | } 45 | 46 | vector sortSerials(vector a) { 47 | sort(begin(a), end(a), compareSerials); 48 | return a; 49 | } 50 | -------------------------------------------------------------------------------- /D2L1/SnowyWinter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int snowyHighwayLength(vector const &begs, vector const &ends) { 6 | vector a(10001, 0); 7 | for (int i = 0; i != begs.size(); ++i) { 8 | for (int j = begs[i]; j < ends[i]; ++j) { 9 | a[j] = 1; 10 | } 11 | } 12 | return accumulate(begin(a), end(a), 0); 13 | } 14 | -------------------------------------------------------------------------------- /D2L1/Target.hs: -------------------------------------------------------------------------------- 1 | module Target where 2 | 3 | draw :: Int -> [String] 4 | draw 1 = [ "#" ] 5 | draw n = (surround . draw) (n - 4) 6 | 7 | surround :: [String] -> [String] 8 | surround spiral = top ++ map addSideMargin spiral ++ bottom where 9 | top = getTopMargin (head spiral) 10 | bottom = reverse top 11 | 12 | getTopMargin :: String -> [String] 13 | getTopMargin s = [ "##" ++ s ++ "##" 14 | , addSideMargin (replicate (length s) ' ') ] 15 | 16 | addSideMargin :: String -> String 17 | addSideMargin s = "# " ++ s ++ " #" 18 | -------------------------------------------------------------------------------- /D2L1/TeamsSelection.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | string simulate(vector const &a, vector const &b) { 6 | int n = a.size(); 7 | string ret(n, '0'); 8 | 9 | int ia = 0, ib = 0; 10 | for (int i = 0; i < n; ++i) { 11 | while (ia < n && ret[a[ia] - 1] != '0') { 12 | ++ia; 13 | } 14 | if (ia < n) { 15 | ret[a[ia] - 1] = '1'; 16 | } 17 | while (ib < n && ret[b[ib] - 1] != '0') { 18 | ++ib; 19 | } 20 | if (ib < n) { 21 | ret[b[ib] - 1] = '2'; 22 | } 23 | } 24 | 25 | return ret; 26 | } 27 | -------------------------------------------------------------------------------- /D2L1/TrainingCamp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | vector determineSolvers(vector const &a, 6 | vector const &b) { 7 | int n = a.size(), m = a[0].size(), k = b.size(); 8 | string empty(k, 'X'); vector ret(n, empty); 9 | for (int i = 0; i != n; ++i) 10 | for (int j = 0; j != k; ++j) 11 | for (int x = 0; x != m; ++x) 12 | if (a[i][x] == '-' && b[j][x] == 'X') 13 | { 14 | ret[i][j] = '-'; 15 | break; 16 | } 17 | return ret; 18 | } -------------------------------------------------------------------------------- /D2L1/TrainingCamp.hs: -------------------------------------------------------------------------------- 1 | module TrainingCamp where 2 | 3 | canSolve :: String -> String -> Char 4 | canSolve student prob = g $ and $ map (uncurry f) $ zip student prob 5 | where f _ '-' = True 6 | f 'X' 'X' = True 7 | f _ _ = False 8 | g True = 'X' 9 | g False = '-' 10 | 11 | determineSolvers :: [String] -> [String] -> [String] 12 | determineSolvers students probs = 13 | map (\student -> map (canSolve student) probs) students -------------------------------------------------------------------------------- /D2L1/TrainingCamp.java: -------------------------------------------------------------------------------- 1 | public class TrainingCamp { 2 | String[] determineSolvers(String[] a, 3 | String[] b) { 4 | int n = a.length, m = a[0].length(), p = b.length; 5 | String[] ret = new String[n]; 6 | for (int i = 0; i < n; ++i) { 7 | StringBuffer sb = new StringBuffer(); 8 | for (int j = 0; j < p; ++j) { 9 | char c = 'X'; 10 | for (int k = 0; k < m; ++k) { 11 | if (a[i].charAt(k) == '-' && 12 | b[j].charAt(k) == 'X') { 13 | c = '-'; 14 | break; 15 | } 16 | } 17 | sb.append(c); 18 | } 19 | ret[i] = sb.toString(); 20 | } 21 | return ret; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /D2L1/UnluckyNumbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int count(int lower, int upper, int n) { 6 | return (upper - n + 1) * (n - lower + 1) - 1; 7 | } 8 | 9 | int getCount(vector a, int n) { 10 | sort(begin(a), end(a)); 11 | for (int i = a.size() - 1; i >= 0; --i) { 12 | if (n == a[i]) { 13 | return 0; 14 | } 15 | if (n > a[i]) { 16 | return count(a[i] + 1, a[i + 1] - 1, n); 17 | } 18 | } 19 | return count(1, a[0] - 1, n); 20 | } 21 | -------------------------------------------------------------------------------- /D2L1/WidgetRepairs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int days(vector const &a, int lim) { 7 | int ret = 0, n = a.size(), x = 0; 8 | for (int i = 0; i != n; ++i) { 9 | x += a[i]; 10 | if (x > 0) { 11 | ++ret; 12 | x = max(0, x - lim); 13 | } 14 | } 15 | ret += x / lim + (x % lim != 0); 16 | return ret; 17 | } 18 | -------------------------------------------------------------------------------- /D2L2/AlternateColors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class Ball { 7 | public: 8 | string name; 9 | int64 number; 10 | 11 | Ball(string const &name, int64 number) 12 | : name(name), number(number) {} 13 | }; 14 | bool operator< (Ball const &x, Ball const &y) { 15 | return x.number < y.number; 16 | } 17 | 18 | string getColor(int64 r, int64 g, int64 b, int64 k) { 19 | vector a = { Ball("RED", r) 20 | , Ball("GREEN", g) 21 | , Ball("BLUE", b) }; 22 | while (!a.empty()) { 23 | int64 y = min_element(begin(a), end(a))->number; 24 | 25 | int64 x = y * a.size(); 26 | if (x >= k) { 27 | return a[(k + a.size() - 1) % a.size()].name; 28 | } 29 | k -= x; 30 | 31 | vector b = a; a.clear(); 32 | for (Ball& ball : b) { 33 | if ((ball.number -= y) > 0) { 34 | a.push_back(ball); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /D2L2/CasketOfStarEasy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int dp[1024], n; 6 | vector a; 7 | 8 | int go(int m) { 9 | if (dp[m] != -1) { 10 | return dp[m]; 11 | } 12 | int ret = 0; 13 | 14 | vector is; 15 | for (int i = 0; i != n; ++i) { 16 | if (m & (1 << i)) { 17 | is.push_back(i); 18 | } 19 | } 20 | 21 | for (int j = 1; j < is.size() - 1; ++j) { 22 | ret = max(ret, a[is[j - 1]] * a[is[j + 1]] + go(m ^ (1 << is[j]))); 23 | } 24 | 25 | dp[m] = ret; 26 | return ret; 27 | } 28 | 29 | int maxEnergy(vector const &weight) { 30 | n = weight.size(); a = weight; 31 | fill(dp, dp + 1024, -1); 32 | return go((1 << n) - 1); 33 | } 34 | -------------------------------------------------------------------------------- /D2L2/CoinsGameEasy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | bool seen[20][20][20][20]; 8 | int dy[] = {-1, 1, 0, 0}, 9 | dx[] = { 0, 0, -1, 1}; 10 | int h, w; 11 | 12 | struct Pos { 13 | int y; 14 | int x; 15 | }; 16 | 17 | struct Node { 18 | Pos p; 19 | Pos q; 20 | int step; 21 | }; 22 | 23 | bool inside(Pos const& p) { 24 | return p.y < h && p.y >= 0 25 | && p.x < w && p.x >= 0; 26 | } 27 | 28 | int minimalSteps(vector const &board) { 29 | h = board.size(); 30 | w = board[0].size(); 31 | 32 | vector initCoins; 33 | for (int y = 0; y < h; ++y) { 34 | for (int x = 0; x < w; ++x) { 35 | if (board[y][x] == 'o') { 36 | initCoins.push_back(Pos{y, x}); 37 | } 38 | } 39 | } 40 | 41 | queue nodes; 42 | nodes.push(Node{initCoins[0], initCoins[1], 0}); 43 | memset(seen, false, sizeof seen); 44 | 45 | while (!nodes.empty()) { 46 | Node node = nodes.front(); nodes.pop(); 47 | Pos p = node.p, q = node.q; int step = node.step; 48 | 49 | switch(inside(p) + inside(q)) { 50 | case 0: continue; 51 | case 1: return step; 52 | } 53 | 54 | if (seen[p.y][p.x][q.y][q.x] || step == 10) { 55 | continue; 56 | } 57 | seen[p.y][p.x][q.y][q.x] = true; 58 | seen[q.y][q.x][p.y][p.x] = true; 59 | 60 | for (int i = 0; i < 4; ++i) { 61 | Pos pp = {p.y + dy[i], p.x + dx[i]}; 62 | Pos qq = {q.y + dy[i], q.x + dx[i]}; 63 | if (inside(pp) && board[pp.y][pp.x] == '#') pp = p; 64 | if (inside(qq) && board[qq.y][qq.x] == '#') qq = q; 65 | nodes.push(Node{pp, qq, step + 1}); 66 | } 67 | } 68 | 69 | return -1; 70 | } 71 | -------------------------------------------------------------------------------- /D2L2/GravityBomb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | vector aftermath(vector const &board) { 6 | int w = board[0].size(), 7 | h = board.size(); 8 | 9 | vector depths; int dmin = 51; 10 | for (int x = 0; x < w; ++x) { 11 | int depth = 0; 12 | for (int y = 0; y < h; ++y) 13 | if (board[y][x] == 'X') ++depth; 14 | depths.push_back(depth); 15 | if (depth < dmin) dmin = depth; 16 | } 17 | for (int i = 0; i < depths.size(); ++i) 18 | depths[i] -= dmin; 19 | 20 | string none(w, '.'); 21 | vector ret(h, none); 22 | for (int x = 0; x < w; ++x) 23 | for (int y = 0; y < depths[x]; ++y) 24 | ret[h - y - 1][x] = 'X'; 25 | return ret; 26 | } -------------------------------------------------------------------------------- /D2L2/GravityBomb.hs: -------------------------------------------------------------------------------- 1 | module GravityBomb where 2 | import Data.List 3 | 4 | boardToDepths :: [[Char]] -> [Int] 5 | boardToDepths = map $ length . filter (== 'X') 6 | 7 | simplifyDepths :: [Int] -> [Int] 8 | simplifyDepths xs = map (\x -> x - y) xs 9 | where y = minimum xs 10 | 11 | depthsToBoard :: Int -> [Int] -> [[Char]] 12 | depthsToBoard n = map (\d -> replicate (n - d) '.' ++ replicate d 'X') 13 | 14 | aftermath :: [String] -> [String] 15 | aftermath board = transpose . depthsToBoard (length board) . 16 | simplifyDepths . boardToDepths . transpose $ board -------------------------------------------------------------------------------- /D2L2/GravityBomb.java: -------------------------------------------------------------------------------- 1 | public class GravityBomb { 2 | String[] aftermath(String[] board) { 3 | int w = board[0].length(), 4 | h = board.length; 5 | 6 | int[] depths = new int[w]; int min = 51; 7 | for (int x = 0; x < w; ++x) { 8 | depths[x] = 0; 9 | for (int y = 0; y < h; ++y) 10 | if (board[y].charAt(x) == 'X') ++depths[x]; 11 | if (depths[x] < min) min = depths[x]; 12 | } 13 | for (int i = 0; i < w; ++i) 14 | depths[i] = h - (depths[i] - min); 15 | 16 | char[][] temp = new char[h][w]; 17 | for (int x = 0; x < w; ++x) { 18 | for (int y = 0; y < depths[x]; ++y) 19 | temp[y][x] = '.'; 20 | for (int y = depths[x]; y < h; ++y) 21 | temp[y][x] = 'X'; 22 | } 23 | 24 | String[] ret = new String[h]; 25 | for (int i = 0; i < h; ++i) 26 | ret[i] = new String(temp[i]); 27 | return ret; 28 | } 29 | } -------------------------------------------------------------------------------- /D2L2/Jumping.hs: -------------------------------------------------------------------------------- 1 | module Jumping where 2 | 3 | toString :: Bool -> String 4 | toString False = "Not able" 5 | toString True = "Able" 6 | 7 | type Range = (Int, Int) 8 | 9 | canReach :: Int -> Int -> Range -> Bool 10 | canReach x y (lo, hi) = z >= lo * lo && z <= hi * hi where 11 | z = x * x + y * y 12 | 13 | -- Draw circles to understand this code (hint: doughnut shape) 14 | jump :: Range -> Int -> Range 15 | jump (lo, hi) x | x <= lo = (lo - x, hi + x) 16 | | x <= hi = (0 , hi + x) 17 | | otherwise = (x - hi, hi + x) 18 | 19 | ableToGet :: Int -> Int -> [Int] -> String 20 | ableToGet x y = toString . canReach x y . foldl jump (0, 0) 21 | -------------------------------------------------------------------------------- /D2L2/MovieSeating.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | long long perms(int k, int n) { 6 | long long ret = 1; 7 | for (int i = n - k + 1; i <= n; ++i) 8 | ret *= i; 9 | return ret; 10 | } 11 | long long getSeatings(int k, vector const &hall) { 12 | long long ret = 0; 13 | int h = hall.size(), 14 | w = hall[0].size(); 15 | for (int i = 0; i < h; ++i) { 16 | int n = 0; 17 | for (int j = 0; j < w; ++j) 18 | if (hall[i][j] == '.') ++n; 19 | ret += perms(k, n); 20 | } 21 | for (int j = 0; j < w; ++j) { 22 | int n = 0; 23 | for (int i = 0; i < h; ++i) 24 | if (hall[i][j] == '.') ++n; 25 | ret += perms(k, n); 26 | } 27 | return k == 1 ? ret/2 : ret; 28 | } 29 | -------------------------------------------------------------------------------- /D2L2/MovieSeating.hs: -------------------------------------------------------------------------------- 1 | module MovieSeating where 2 | 3 | import Data.List 4 | import Foreign.Marshal.Utils (fromBool) 5 | 6 | count :: Eq a => (a -> Bool) -> [a] -> Int 7 | count f = sum . map (fromBool . f) 8 | 9 | countEmpty :: String -> Int 10 | countEmpty = count (== '.') 11 | 12 | perms :: Int -> Int -> Integer 13 | perms k n = foldl f 1 [(n - k + 1) .. n] 14 | where f x n = x * toInteger n 15 | 16 | arrange :: Int -> [String] -> Integer 17 | arrange k = sum . map (perms k . countEmpty) 18 | 19 | getSeatings :: Int -> [String] -> Integer 20 | getSeatings 1 hall = toInteger . sum . map countEmpty $ hall 21 | getSeatings k hall = arrange k hall + arrange k (transpose hall) 22 | -------------------------------------------------------------------------------- /D2L2/MovieSeating.java: -------------------------------------------------------------------------------- 1 | public class MovieSeating { 2 | public long perms(int n, int k) { 3 | if (n < k) { 4 | return 0; 5 | } 6 | long ret = 1; 7 | for (int i = n; i > n - k; --i) { 8 | ret *= i; 9 | } 10 | return ret; 11 | } 12 | public long getSeatings(int k, 13 | String[] hall) { 14 | long ret = 0; 15 | for (int i = 0; i < hall.length; ++i) { 16 | int n = 0; 17 | for (int j = 0; j < hall[i].length(); ++j) { 18 | if (hall[i].charAt(j) == '.') { 19 | ++n; 20 | } 21 | } 22 | ret += perms(n, k); 23 | } 24 | for (int i = 0; i < hall[0].length(); ++i) { 25 | int n = 0; 26 | for (int j = 0; j < hall.length; ++j) { 27 | if (hall[j].charAt(i) == '.') { 28 | ++n; 29 | } 30 | } 31 | ret += perms(n, k); 32 | } 33 | return k == 1 ? (ret / 2) : ret; 34 | } 35 | } -------------------------------------------------------------------------------- /D2L2/PseudoPrimeTest.cpp: -------------------------------------------------------------------------------- 1 | int modulus(int b, int n, int p) { 2 | if (n == 0) { 3 | return 1; 4 | } 5 | if (n == 1) { 6 | return b % p; 7 | } 8 | int k = modulus(b, n/2, p); 9 | return ((k * k % p) * modulus(b, n % 2, p)) % p; 10 | } 11 | 12 | int firstFail(int q) { 13 | for (int b = 2; b < q; ++b) { 14 | if (modulus(b, q - 1, q) != 1) { 15 | return b; 16 | } 17 | } 18 | return q; 19 | } 20 | -------------------------------------------------------------------------------- /D2L2/ThreeTeleports.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct Point { 8 | int x; 9 | int y; 10 | }; 11 | 12 | struct Teleport { 13 | Point p; 14 | Point q; 15 | }; 16 | 17 | int distance(Point p, Point q) { 18 | return abs(q.x - p.x) + abs(q.y - p.y); 19 | } 20 | 21 | vector parse(vector const &input) { 22 | vector ret; 23 | for (auto line : input) { 24 | int x1, y1, x2, y2; stringstream(line) >> x1 >> y1 >> x2 >> y2; 25 | Point p = {x1, y1}, q = {x2, y2}; Teleport t = {p, q}; 26 | ret.push_back(t); 27 | } 28 | return ret; 29 | } 30 | 31 | int64 shortest(Point p, Point q, vector a) { 32 | int64 ret = distance(p, q); 33 | for (int i = 0; i < a.size(); ++i) { 34 | vector b; 35 | for (int j = 0; j < a.size(); ++j) { 36 | if (j != i) { 37 | b.push_back(a[j]); 38 | } 39 | } 40 | ret = min(ret, distance(p, a[i].p) + 10 + shortest(a[i].q, q, b)); 41 | ret = min(ret, distance(p, a[i].q) + 10 + shortest(a[i].p, q, b)); 42 | } 43 | return ret; 44 | } 45 | 46 | int shortestDistance(int xMe, int yMe, int xHome, int yHome, 47 | vector const &teleports) { 48 | Point p = {xMe, yMe}, q = {xHome, yHome}; 49 | return (int) shortest(p, q, parse(teleports)); 50 | } 51 | -------------------------------------------------------------------------------- /D2L3/BestApproximationDiv2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int quality(int a, int b, vector const &d) { 7 | int x = 1; 8 | for (int i = 0; i != d.size(); ++i) { 9 | int aa = 10 * a; 10 | if (aa/b == d[i]) { 11 | a = aa % b; 12 | ++x; 13 | } 14 | else break; 15 | } 16 | return x; 17 | } 18 | double todec(vector const &d, int n) { 19 | double ret = 0; 20 | for (int i = 0, j = 10; i != n; ++i) { 21 | ret += (double)(d[i]) / j; 22 | j *= 10; 23 | } 24 | return ret; 25 | } 26 | bool update(int a, int b, vector const &d, 27 | int &retx, int &reta, int &retb, double &y) { 28 | int x = quality(a, b, d); 29 | if (x > retx) { 30 | retx = x; reta = a; retb = b; 31 | y = todec(d, x - 1); 32 | return true; 33 | } 34 | return (x == retx); 35 | } 36 | string findFraction(int maxDen, 37 | string const &number) { 38 | vector d; 39 | for (int i = 2; i != number.size(); ++i) 40 | d.push_back(number[i] - '0'); 41 | 42 | int retx = 0, reta, retb; 43 | double y = 0; 44 | for (int b = 1; b <= maxDen; ++b) { 45 | int pivot = y*b; 46 | for (int a = pivot; a >= 0; --a) 47 | if (!update(a, b, d, retx, reta, retb, y)) break; 48 | for (int a = pivot + 1; a < b; ++a) 49 | if (!update(a, b, d, retx, reta, retb, y)) break; 50 | } 51 | 52 | ostringstream oss; 53 | oss << reta << '/' << retb << " has " << retx << " exact digits"; 54 | return oss.str(); 55 | } 56 | -------------------------------------------------------------------------------- /D2L3/BestApproximationDiv2.hs: -------------------------------------------------------------------------------- 1 | module BestApproximationDiv2 where 2 | import Data.Char 3 | import Data.List 4 | import Data.Maybe 5 | 6 | showResult :: (Int, Int, Int) -> String 7 | showResult (a, b, x) = concat [show a, "/", show b, " has ", show x, " exact digits"] 8 | 9 | compareDigits :: [Int] -> [Int] -> Ordering 10 | compareDigits xs [] = EQ 11 | compareDigits (x:xs) (y:ys) = case compare x y of 12 | EQ -> compareDigits xs ys 13 | order -> order 14 | 15 | toDigit :: Char -> Int 16 | toDigit c = ord c - ord '0' 17 | 18 | preciseDivision :: Int -> Int -> [Int] 19 | preciseDivision a b = d : preciseDivision r b 20 | where (d, r) = divMod (10 * a) b 21 | 22 | estimate :: [Int] -> Double 23 | estimate = sum . zipWith (flip (/)) (iterate (*10) 10) . 24 | map fromIntegral 25 | 26 | bestNumerator :: [Int] -> Double -> Int -> Maybe Int 27 | bestNumerator ds p b = 28 | case find atLeast . map (pair ds b) $ [pivot .. ] of 29 | Just (a, EQ) -> Just a 30 | otherwise -> Nothing 31 | where pivot = truncate $ p * fromIntegral b 32 | pair ds b a = (a, compareDigits (preciseDivision a b) ds) 33 | atLeast (a, order) = order /= LT 34 | 35 | bestResult :: Int -> [Int] -> Maybe (Int, Int, Int) 36 | bestResult n ds = fromMaybe Nothing . find isJust . 37 | map (toResult ds $ estimate ds) $ [1..n] 38 | where toResult ds p b = case bestNumerator ds p b of 39 | Just a -> Just (a, b, 1 + length ds) 40 | Nothing -> Nothing 41 | 42 | findFraction' :: Int -> [Int] -> (Int, Int, Int) 43 | findFraction' n = fromJust . last . takeWhile isJust . 44 | map (bestResult n) . inits 45 | 46 | findFraction :: Int -> String -> String 47 | findFraction n = showResult . findFraction' n . 48 | map toDigit . tail . tail 49 | -------------------------------------------------------------------------------- /D2L3/BestApproximationDiv2.java: -------------------------------------------------------------------------------- 1 | public class BestApproximationDiv2 { 2 | public String buildResult(int a, int b, int x) { 3 | StringBuffer sb = new StringBuffer(); 4 | sb.append(a); sb.append('/'); sb.append(b); 5 | sb.append(" has "); sb.append(x); sb.append(" exact digits"); 6 | return sb.toString(); 7 | } 8 | public boolean satisfy(int a, int b, String s) { 9 | for (int i = 2; i < s.length(); ++i) { 10 | int d = s.charAt(i) - '0'; 11 | a = 10 * a; 12 | if ((a / b) != d) return false; 13 | a = a % b; 14 | } 15 | return true; 16 | } 17 | public String findFraction(int maxDen, 18 | String number) { 19 | int reta = 0, retb = 1, retx = 1; 20 | int hi = number.length() - 1, lo = 2; 21 | while (lo <= hi) { 22 | int x = (lo + hi)/2; 23 | String sub = number.substring(0, x + 1); 24 | double y = Double.parseDouble(sub); 25 | boolean ok = false; 26 | for (int b = 1; b <= maxDen; ++b) { 27 | int a = (int) Math.round(y * b); 28 | if (satisfy(a, b, sub)) { 29 | reta = a; retb = b; retx = x; 30 | ok = true; break; 31 | } 32 | } 33 | if (ok) lo = x + 1; else hi = x - 1; 34 | } 35 | return buildResult(reta, retb, retx); 36 | } 37 | } -------------------------------------------------------------------------------- /D2L3/ComplexIntegers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | bool isPrime(int n) { 7 | for (int i = 2; i*i <= n; ++i) { 8 | if (n % i == 0) { 9 | return false; 10 | } 11 | } 12 | return true; 13 | } 14 | 15 | enum Kind { 16 | ZERO, UNIT, PRIME, COMPOSITE 17 | }; 18 | 19 | Kind getKind(int a, int b) { 20 | if (a == 0 && b == 0) { 21 | return ZERO; 22 | } 23 | a = abs(a); b = abs(b); 24 | if (a > b) { 25 | swap(a, b); 26 | } 27 | if (a == 0) { 28 | if (b == 1) { 29 | return UNIT; 30 | } 31 | return b % 4 == 3 && isPrime(b) ? PRIME : COMPOSITE; 32 | } 33 | return isPrime(a * a + b * b) ? PRIME : COMPOSITE; 34 | } 35 | 36 | vector classify(vector const &realPart, 37 | vector const &imaginaryPart) { 38 | vector ret; 39 | for (int i = 0; i != realPart.size(); ++i) { 40 | switch (getKind(realPart[i], imaginaryPart[i])) { 41 | case ZERO: ret.push_back("zero"); break; 42 | case UNIT: ret.push_back("unit"); break; 43 | case PRIME: ret.push_back("prime"); break; 44 | case COMPOSITE: ret.push_back("composite"); break; 45 | } 46 | } 47 | return ret; 48 | } 49 | -------------------------------------------------------------------------------- /D2L3/DiskScheduler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int n; 6 | vector a; 7 | 8 | int cost(int x, int y, int d) { 9 | x = (x + n) % n; 10 | y = (y + n) % n; 11 | return ((a[y] - a[x]) * d + 100) % 100; 12 | } 13 | 14 | int optimize(int start, vector const §ors) { 15 | a = sectors; 16 | a.push_back(start); 17 | sort(begin(a), end(a)); 18 | n = a.size(); 19 | 20 | int k = find(begin(a), end(a), start) - begin(a); 21 | int ret = 100; 22 | 23 | for (int i = 0; i < n; ++i) { 24 | ret = min(ret, cost(k, i, -1) + cost(i, i - 1, 1)); 25 | ret = min(ret, cost(k, i, 1) + cost(i, i + 1, -1)); 26 | } 27 | 28 | return ret; 29 | } 30 | -------------------------------------------------------------------------------- /D2L3/DivisibleSequence.cpp: -------------------------------------------------------------------------------- 1 | // Solution explained: http://apps.topcoder.com/wiki/display/tc/SRM+565 2 | 3 | const int MOD = 1000000009; 4 | 5 | long long modPow(int p, int q) { 6 | if (q == 0) { 7 | return 1; 8 | } else if (q == 1) { 9 | return p; 10 | } 11 | long long ret = modPow(p, q/2); 12 | return ret * ret % MOD * modPow(p, q % 2) % MOD; 13 | } 14 | 15 | long long combination(int n, int k) { 16 | long long upper = 1; 17 | for (int i = n; i > n - k; --i) { 18 | upper = upper * i % MOD; 19 | } 20 | long long lower = 1; 21 | for (int i = 1; i <= k; ++i) { 22 | lower = lower * i % MOD; 23 | } 24 | return upper * modPow(lower, MOD - 2) % MOD; 25 | } 26 | 27 | int count(int n, int h) { 28 | long long ret = 1; 29 | for (int p = 2; p <= n/p; ++p) { 30 | int q = 0; 31 | while (n % p == 0) { 32 | ++q; 33 | n /= p; 34 | } 35 | ret = ret * combination(h - 1 + q, q) % MOD; 36 | } 37 | if (n > 1) { 38 | ret = ret * h % MOD; 39 | } 40 | return (int) ret; 41 | } 42 | -------------------------------------------------------------------------------- /D2L3/EngineersPrimes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX = 100000; 5 | const int LIM = 1000000; 6 | vector ps; 7 | 8 | bool isPrime(int n) { 9 | for (auto p : ps) { 10 | if (p * p > n) { 11 | return true; 12 | } else if (n % p == 0) { 13 | return false; 14 | } 15 | } 16 | } 17 | 18 | int nthPrime(int n) { 19 | bool a[LIM]; fill(a, a + LIM, true); 20 | a[0] = false; a[1] = false; a[2] = true; 21 | 22 | for (int i = 2; i < LIM; ++i) { 23 | if (!a[i]) { 24 | continue; 25 | } 26 | ps.push_back(i); 27 | if (ps.size() == n) { 28 | return i; 29 | } 30 | for (int j = i + i; j < LIM; j += i) { 31 | a[j] = false; 32 | } 33 | } 34 | 35 | for (int i = LIM + 1; ; ++i) { 36 | if (!isPrime(i)) { 37 | continue; 38 | } 39 | ps.push_back(i); 40 | if (ps.size() == n) { 41 | return i; 42 | } 43 | } 44 | } 45 | 46 | int64 smallestNonPrime(int N) { 47 | int64 p = nthPrime(N + 1); 48 | return p * p; 49 | } 50 | -------------------------------------------------------------------------------- /D2L3/KthElement.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int bitCount(int n) { 5 | int ret = 0; 6 | while (n) { 7 | ++ret; 8 | n &= (n - 1); 9 | } 10 | return ret; 11 | } 12 | 13 | int find(int a, int b, int k) { 14 | vector xs = {0, b}; 15 | int start = -1, period = -1; 16 | for (int i = 2; start == -1 ; ++i) { 17 | int x = a * bitCount(xs[i - 1]) + b; 18 | for (int j = i - 1; j >= 0; --j) { 19 | if (x == xs[j]) { 20 | start = j; 21 | period = i - j; 22 | } 23 | } 24 | xs.push_back(x); 25 | } 26 | return k > start ? xs[(k - start) % period + start] : xs[k]; 27 | } 28 | -------------------------------------------------------------------------------- /D2L3/LightedPanels.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | typedef unsigned long long uint64; 7 | 8 | const int MAX = 65; 9 | int w, h; 10 | uint64 init, FULL, ONE = 1; 11 | 12 | uint64 bit(int y, int x) { 13 | return ONE << ((y * w) + x); 14 | } 15 | 16 | void input(vector const &board) { 17 | h = board.size(); w = board[0].size(); init = 0; FULL = 0; 18 | for (int y = 0; y != h; ++y) { 19 | for (int x = 0; x != w; ++x) { 20 | auto b = bit(y, x); 21 | if (board[y][x] == '*') { 22 | init |= b; 23 | } 24 | FULL |= b; 25 | } 26 | } 27 | } 28 | 29 | void touch(uint64 &a, int y, int x) { 30 | for (int dx = -1; dx <= 1; ++dx) { 31 | for (int dy = -1; dy <= 1; ++dy) { 32 | int xx = x + dx, yy = y + dy; 33 | if (xx >= 0 && xx < w && yy >= 0 && yy < h) { 34 | a ^= bit(yy, xx); 35 | } 36 | } 37 | } 38 | } 39 | 40 | void apply(uint64 &a, int mask) { 41 | for (int x = 0; x != w; ++x) { 42 | if (mask & (1 << x)) { 43 | touch(a, 0, x); 44 | } 45 | } 46 | for (int y = 1; y != h; ++y) { 47 | if (mask & (1 << (w + y - 1))) { 48 | touch(a, y, 0); 49 | } 50 | } 51 | } 52 | 53 | int bitsize(int mask) { 54 | int ret = 0; 55 | for (; mask; mask >>= 1) { 56 | ret += (mask & 1); 57 | } 58 | return ret; 59 | } 60 | 61 | int solve(uint64 &a) { 62 | int ret = 0; 63 | for (int y = 1; y != h; ++y) { 64 | for (int x = 1; x != w; ++x) { 65 | if ((a & bit(y - 1, x - 1)) == 0) { 66 | touch(a, y, x); 67 | ++ret; 68 | } 69 | } 70 | } 71 | return a == FULL ? ret : MAX; 72 | } 73 | 74 | int minTouch(vector const &board) { 75 | input(board); 76 | int ret = MAX; 77 | for (int mask = 0; mask < (1 << (w + h - 1)); ++mask) { 78 | auto a = init; apply(a, mask); 79 | ret = min(ret, bitsize(mask) + solve(a)); 80 | } 81 | return ret == MAX ? -1 : ret; 82 | } 83 | -------------------------------------------------------------------------------- /D2L3/MagicalGirl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct Witch { 6 | int day; 7 | double win; 8 | int gain; 9 | }; 10 | bool operator<(Witch const &x, Witch const &y) { 11 | return x.day < y.day; 12 | } 13 | 14 | double maxExpectation(int M, 15 | vector const &day, 16 | vector const &win, 17 | vector const &gain) { 18 | int N = day.size(); 19 | 20 | vector a; Witch dumb = {0, 0, 0}; a.push_back(dumb); 21 | for (int i = 0; i != N; ++i) { 22 | Witch witch = {day[i], win[i] / 100.0, gain[i]}; a.push_back(witch); 23 | } 24 | sort(begin(a), end(a)); 25 | 26 | vector> dp(N + 1, vector(M + 1, 0)); 27 | for (int j = 1; j <= M; ++j) { 28 | dp[N][j] = a[N].day + j; 29 | } 30 | for (int i = N - 1; i >= 0; --i) { 31 | Witch &x = a[i + 1]; 32 | int today = a[i].day, gap = x.day - today; 33 | for (int j = 1; j <= min(gap, M); ++j) { 34 | dp[i][j] = today + j; 35 | } 36 | for (int j = gap + 1; j <= M; ++j) { 37 | int life = j - gap; 38 | dp[i][j] = max(x.win * dp[i + 1][min(M, life + x.gain)] + 39 | (1- x.win) * x.day, dp[i + 1][life]); 40 | } 41 | } 42 | return dp[0][M]; 43 | } 44 | -------------------------------------------------------------------------------- /D2L3/MagicalSquare.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | typedef long long int64; 7 | 8 | string p, q, r, x, y, z; 9 | 10 | // --- --- --- 11 | // | a | b | c | x 12 | // --- --- --- 13 | // | d | e | f | y 14 | // --- --- --- 15 | // | g | h | k | z 16 | // --- --- --- 17 | // p q r 18 | 19 | bool isValid(int a, int b, int d, int e) { 20 | int g = p.size() - (a + d); 21 | if (g < 0) { 22 | return false; 23 | } 24 | int h = q.size() - (b + e); 25 | if (h < 0) { 26 | return false; 27 | } 28 | int c = x.size() - (a + b), 29 | f = y.size() - (d + e), 30 | k = z.size() - (g + h); 31 | if (k < 0) { 32 | return false; 33 | } 34 | return equal(x.begin(), x.begin() + a, p.begin()) 35 | && equal(y.begin(), y.begin() + d, p.begin() + a) 36 | && equal(z.begin(), z.begin() + g, p.begin() + a + d) 37 | && equal(x.begin() + a, x.begin() + a + b, q.begin()) 38 | && equal(y.begin() + d, y.begin() + d + e, q.begin() + b) 39 | && equal(z.begin() + g, z.begin() + g + h, q.begin() + b + e) 40 | && equal(x.begin() + a + b, x.end(), r.begin()) 41 | && equal(y.begin() + d + e, y.end(), r.begin() + c) 42 | && equal(z.begin() + g + h, z.end(), r.begin() + c + f); 43 | } 44 | 45 | int64 getCount(vector const &rowStrings, 46 | vector const &columnStrings) { 47 | x = rowStrings[0]; y = rowStrings[1]; z = rowStrings[2]; 48 | p = columnStrings[0]; q = columnStrings[1]; r = columnStrings[2]; 49 | 50 | if (x.size() + y.size() + z.size() != 51 | p.size() + q.size() + r.size()) { 52 | return 0; 53 | } 54 | 55 | int64 ret = 0; 56 | for (int a = 0; a <= x.size(); ++a) { 57 | for (int b = 0; b <= x.size() - a; ++b) { 58 | for (int d = 0; d <= y.size(); ++d) { 59 | for (int e = 0; e <= y.size() - d; ++e) { 60 | ret += isValid(a, b, d, e); 61 | } 62 | } 63 | } 64 | } 65 | return ret; 66 | } 67 | -------------------------------------------------------------------------------- /D2L3/MarbleCollectionGame.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int n; // number of cells 8 | vector a; // marble value at cell i 9 | vector> b; // all adjacent cells of cell i 10 | vector> c; // is there a path between cell i and cell j 11 | 12 | int N; // number of super cells 13 | vector super; // root cell of super cell i 14 | vector A; // total value of super cell i 15 | vector> B; // all adjacent super cells of super cell i 16 | vector dp; // how much can we collect if we start from super cell i 17 | 18 | void convert(vector const &board) { 19 | int h = board.size(), w = board[0].size(), i = 0; 20 | n = h * w; a.assign(n, 0); b.assign(n, vector()); 21 | for (int y = 0; y != h; ++y) { 22 | for (int x = 0; x != w; ++x) { 23 | switch (board[y][x]) { 24 | case '#': 25 | break; 26 | case 'U': 27 | if (y > 0) { 28 | b[i].push_back(i - w); 29 | } 30 | break; 31 | case 'L': 32 | if (x > 0) { 33 | b[i].push_back(i - 1); 34 | } 35 | break; 36 | default: 37 | a[i] = board[y][x] - '0'; 38 | } 39 | if (board[y][x] != '#') { 40 | if (y < h - 1) { 41 | b[i].push_back(i + w); 42 | } 43 | if (x < w - 1) { 44 | b[i].push_back(i + 1); 45 | } 46 | } 47 | ++i; 48 | } 49 | } 50 | } 51 | 52 | void connect() { 53 | c.assign(n, vector(n, false)); 54 | for (int root = 0; root != n; ++root) { 55 | vector seen(n, false); 56 | queue Q; Q.push(root); 57 | while (!Q.empty()) { 58 | int u = Q.front(); Q.pop(); 59 | if (seen[u]) { 60 | continue; 61 | } 62 | seen[u] = true; 63 | for (int w : b[u]) { 64 | c[root][w] = true; 65 | Q.push(w); 66 | } 67 | } 68 | } 69 | } 70 | 71 | void merge() { 72 | vector seen(n, false); 73 | for (int u = 0; u != n; ++u) { 74 | if (seen[u]) { 75 | continue; 76 | } 77 | seen[u] = true; 78 | super.push_back(u); 79 | int sum = a[u]; 80 | for (int w = 0; w != n; ++w) { 81 | if (u != w && c[u][w] && c[w][u]) { 82 | seen[w] = true; 83 | sum += a[w]; 84 | } 85 | } 86 | A.push_back(sum); 87 | } 88 | N = A.size(); B.assign(N, vector()); 89 | for (int i = 0; i != N; ++i) { 90 | for (int j = 0; j != N; ++j) { 91 | if (i != j && c[super[i]][super[j]]) { 92 | B[i].push_back(j); 93 | } 94 | } 95 | } 96 | dp.assign(N, -1); 97 | } 98 | 99 | int collect(int root) { 100 | if (dp[root] == -1) { 101 | int ret = 0; 102 | for (int u : B[root]) { 103 | ret = max(ret, collect(u)); 104 | } 105 | dp[root] = ret + A[root]; 106 | } 107 | return dp[root]; 108 | } 109 | 110 | int collectMarble(vector const &board) { 111 | convert(board); 112 | connect(); 113 | merge(); 114 | return collect(0); 115 | } 116 | -------------------------------------------------------------------------------- /D2L3/MirrorPath.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | vector a; 6 | int w, h; 7 | 8 | void left(int y, int x); 9 | void right(int y, int x); 10 | void up(int y, int x); 11 | void down(int y, int x); 12 | 13 | void down(int y, int x) { 14 | for (int i = y; i < h; ++i) { 15 | switch (a[i][x]) { 16 | case '#': return; 17 | case '`': right(i, x + 1); return; 18 | case '/': left(i, x - 1); return; 19 | case '-': a[i][x] = '+'; break; 20 | default : a[i][x] = '|'; break; 21 | } 22 | } 23 | } 24 | 25 | void up(int y, int x) { 26 | for (int i = y; i >= 0; --i) { 27 | switch (a[i][x]) { 28 | case '#': return; 29 | case '`': left(i, x - 1); return; 30 | case '/': right(i, x + 1); return; 31 | case '-': a[i][x] = '+'; break; 32 | default : a[i][x] = '|'; break; 33 | } 34 | } 35 | } 36 | 37 | void left(int y, int x) { 38 | for (int i = x; i >= 0; --i) { 39 | switch (a[y][i]) { 40 | case '#': return; 41 | case '`': up(y - 1, i); return; 42 | case '/': down(y + 1, i); return; 43 | case '|': a[y][i] = '+'; break; 44 | default : a[y][i] = '-'; break; 45 | } 46 | } 47 | } 48 | 49 | void right(int y, int x) { 50 | for (int i = x; i < w; ++i) { 51 | switch (a[y][i]) { 52 | case '#': return; 53 | case '`': down(y + 1, i); return; 54 | case '/': up(y - 1, i); return; 55 | case '|': a[y][i] = '+'; break; 56 | default : a[y][i] = '-'; break; 57 | } 58 | } 59 | } 60 | 61 | vector path(vector const &map) { 62 | a = map; h = a.size(); w = a[0].size(); 63 | for (int x = 0; x != w; ++x) { 64 | if (a[0][x] == '.') { 65 | down(0, x); 66 | break; 67 | } else if (a[h - 1][x] == '.') { 68 | up(h - 1, x); 69 | break; 70 | } 71 | } 72 | for (int y = 0; y != h; ++y) { 73 | if (a[y][0] == '.') { 74 | right(y, 0); 75 | break; 76 | } else if (a[y][w - 1] == '.') { 77 | left(y, w - 1); 78 | break; 79 | } 80 | } 81 | return a; 82 | } 83 | -------------------------------------------------------------------------------- /D2L3/QuickSums.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int dp[11][11][101]; 7 | vector a; int n; 8 | const int UNDONE = -2, 9 | CANNOT = 11; 10 | 11 | void init() { 12 | for (int lo = 0; lo != n; ++lo) { 13 | for (int hi = 0; hi != n; ++hi) { 14 | for (int sum = 0; sum <= 100; ++sum) { 15 | dp[lo][hi][sum] = UNDONE; 16 | } 17 | } 18 | } 19 | } 20 | 21 | int cost(int lo, int hi, int sum) { 22 | if (dp[lo][hi][sum] != UNDONE) { 23 | return dp[lo][hi][sum]; 24 | } 25 | 26 | int ret = CANNOT, left = 0; 27 | for (int mid = lo; mid <= hi; ++mid) { 28 | left = left * 10 + a[mid]; 29 | if (left > sum) { 30 | break; 31 | } 32 | ret = min(ret, 1 + cost(mid + 1, hi, sum - left)); 33 | } 34 | left = left * 10 + a[hi]; 35 | ret = left == sum ? 0 : ret; 36 | 37 | dp[lo][hi][sum] = ret; 38 | return ret; 39 | } 40 | 41 | int minSums(string const &numbers, int sum) { 42 | n = numbers.size(); 43 | for (int i = 0; i != n; ++i) { 44 | a.push_back(numbers[i] - '0'); 45 | } 46 | init(); 47 | int ret = cost(0, n - 1, sum); 48 | return ret == CANNOT ? -1 : ret; 49 | } 50 | -------------------------------------------------------------------------------- /D2L3/ShortPalindromes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int dp[25][25]; 8 | const int MAX = 25; 9 | string s; 10 | ostringstream oss; 11 | 12 | void init() { 13 | for (int i = 0; i < s.size(); ++i) { 14 | for (int j = 0; j < s.size(); ++j) { 15 | dp[i][j] = MAX; 16 | } 17 | } 18 | } 19 | 20 | int cost(int lo, int hi) { 21 | if (lo >= hi) { 22 | return 0; 23 | } else if (dp[lo][hi] != MAX) { 24 | return dp[lo][hi]; 25 | } 26 | int ret = MAX; 27 | if (s[lo] == s[hi]) { 28 | ret = cost(lo + 1, hi - 1); 29 | } else { 30 | ret = 1 + min(cost(lo + 1, hi), cost(lo, hi - 1)); 31 | } 32 | dp[lo][hi] = ret; 33 | return ret; 34 | } 35 | 36 | void build(int lo, int hi) { 37 | if (lo > hi) { 38 | return; 39 | } else if (lo == hi) { 40 | oss << s[lo]; 41 | return; 42 | } else if (s[lo] == s[hi]) { 43 | oss << s[lo]; 44 | build(lo + 1, hi - 1); 45 | return; 46 | } 47 | int takelo = cost(lo + 1, hi), takehi = cost(lo, hi - 1); 48 | if (takelo < takehi || (takelo == takehi && s[lo] < s[hi])) { 49 | oss << s[lo]; 50 | build(lo + 1, hi); 51 | } else { 52 | oss << s[hi]; 53 | build(lo, hi - 1); 54 | } 55 | } 56 | 57 | string shortest(string const &base) { 58 | s = base; int n = base.size(); 59 | init(); build(0, n - 1); 60 | 61 | string left(oss.str()); 62 | if ((n + cost(0, n - 1)) % 2 == 0) { 63 | oss << left[left.size() - 1]; 64 | } 65 | for (int i = left.size() - 2; i >= 0; --i) { 66 | oss << left[i]; 67 | } 68 | 69 | return oss.str(); 70 | } 71 | -------------------------------------------------------------------------------- /D2L3/TopView.cpp: -------------------------------------------------------------------------------- 1 | // Requires [Topological Sort](http://en.wikipedia.org/wiki/Topological_sort) 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | string const ERROR = "ERROR!"; 10 | 11 | vector a; 12 | vector cards; 13 | 14 | const int N = 10 + 26 + 26; 15 | char indexToCard[N]; 16 | int cardToIndex[256]; 17 | 18 | vector> above(N); 19 | vector under(N, 0); 20 | 21 | void setupConverters() { 22 | for (char c = '0'; c <= '9'; ++c) { 23 | indexToCard[c - '0'] = c; 24 | cardToIndex[c] = c - '0'; 25 | } 26 | for (char c = 'A'; c <= 'Z'; ++c) { 27 | indexToCard[c - 'A' + 10] = c; 28 | cardToIndex[c] = c - 'A' + 10; 29 | } 30 | for (char c = 'a'; c <= 'z'; ++c) { 31 | indexToCard[c - 'a' + 36] = c; 32 | cardToIndex[c] = c - 'a' + 36; 33 | } 34 | } 35 | 36 | bool findConstraints() { 37 | int H = a.size(), W = a[0].size(); 38 | for (int i = 0; i < N; ++i) { 39 | int x1 = 50, y1 = 50, x2 = -1, y2 = -1; 40 | bool found = false; 41 | for (int y = 0; y < H; ++y) { 42 | for (int x = 0; x < W; ++x) { 43 | if (indexToCard[i] == a[y][x]) { 44 | found = true; 45 | x1 = min(x, x1); 46 | y1 = min(y, y1); 47 | x2 = max(x, x2); 48 | y2 = max(y, y2); 49 | } 50 | } 51 | } 52 | if (found) { 53 | cards.push_back(i); 54 | for (int y = y1; y <= y2; ++y) { 55 | for (int x = x1; x <= x2; ++x) { 56 | if (a[y][x] == '.') { 57 | return false; 58 | } 59 | int j = cardToIndex[a[y][x]]; 60 | if (j != i) { 61 | above[i].push_back(j); 62 | under[j]++; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | string topoSort() { 72 | ostringstream oss; 73 | for (int k = 0; k < cards.size(); ++k) { 74 | bool found = false; 75 | for (int i : cards) { 76 | if (under[i] == 0) { 77 | found = true; 78 | for (int j : above[i]) { 79 | under[j]--; 80 | } 81 | under[i] = -1; 82 | oss << indexToCard[i]; 83 | break; 84 | } 85 | } 86 | if (!found) { 87 | return ERROR; 88 | } 89 | } 90 | return oss.str(); 91 | } 92 | 93 | string findOrder(vector const &grid) { 94 | a = grid; 95 | setupConverters(); 96 | if (!findConstraints()) { 97 | return ERROR; 98 | } 99 | return topoSort(); 100 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Solutions to TopCoder problems in C++, Haskell, and other languages. 2 | 3 | All solutions have been tested for correctness with [gettc](https://github.com/seri/gettc), a tool to assist running your TopCoder solutions without the official online arena. 4 | 5 | The problem statement for each solution can be found at [TopCoder Problem Archieve](http://community.topcoder.com/tc?module=ProblemArchive). 6 | 7 | These solutions are written in my own time (that means: not during contest) so I try to make them as clean as clear as possible. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
DirectoryDivisionLevel
D1L11250
D1L21500
D1L311000
D2L12250
D2L22500
D2L321000
48 | --------------------------------------------------------------------------------