// ------------------------------------------------------------------------------------------------ // Get the length of the recurring cycle (zero if it doesn't repeat at all) // ------------------------------------------------------------------------------------------------ static uintn CycleLength(uintn denom) { uintn curr = 1; CTable<uintn> remain; while(curr != 0) { curr *= 10; uintn div = curr / denom; curr -= denom * div; remain.Grow(curr); // -- look through the previous remainders to see if we've started repeating for(uintn i = remain.Count() - 1; i > 0;) { --i; if(remain[i] == curr) return remain.Count() - 1 - i; } } // -- if we exited the loop, we finished the decimal expansion, so there's no cycle return 0; }
// ------------------------------------------------------------------------------------------------ // Recursive function to collect all the combinations of factors // ------------------------------------------------------------------------------------------------ void CFactorizer::CollectFactorCombinations(const CTable<nuint>& factors, nuint curr, nuint prod, CTable<nuint>& divisors) { nuint numfactors = factors.Count(); nuint f = factors[curr]; // -- look for the upper bound of the same factor nuint end = curr; while(end < numfactors && factors[end] == f) ++end; // -- figure out if we're the end of the line and so we should be adding into the table nflag record = end == numfactors; // -- loop over the number of times this factor is repeated and deal with all of them for(nuint i = curr; i <= end; ++i) { if(record) divisors.Grow(prod); else CollectFactorCombinations(factors, end, prod, divisors); prod *= f; } }
// ================================================================================================ // Main // ================================================================================================ int main(sint32 argc, sint8* argv[]) { // -- make sure we're given a file name if(argc < 2) { Log_("You need to give me a filename, please\n"); return 0; } // -- try to open it FILE* fp = NULL; fopen_s(&fp, argv[1], "r"); // -- make sure we could open it if(fp == NULL) { Log_("Don't know that file\n"); return 0; } // -- read stuff uint32 numtests; fscanf_s(fp, "%d", &numtests); CTable<SPerson> people; for(uintn i = 0; i < numtests; ++i) { people.Clear(); uint32 total = 0; uint32 numpeople; fscanf_s(fp, "%d", &numpeople); for(uintn j = 0; j < numpeople; ++j) { uint32 pnt; fscanf_s(fp, "%d", &pnt); people.Grow(SPerson(pnt, uint32(j))); total += pnt; } // -- sort the people by point value people.Sort<SByPoints>(); // -- start with the lowest and add enough to make it equal to the next // -- then add enough to both to make them both equal to the third // -- continue until all the crowd votes are gone real64 remaining = 1.0f; real64 watermark = real64(people[0].points); DebugLog_("Watermark : %Lf\n", watermark); flagn usedup = false; for(uintn j = 1; j < numpeople && !usedup; ++j) { // -- how much do we need to add to all the people so far to get the watermark // -- up to the current entry real64 diff = (real64(people[j].points) - watermark) * real64(j) / real64(total); watermark = real64(people[j].points); DebugLog_("Next person %Lf, diff %Lf (%Lf), remaining %Lf\n", real64(people[j].points), diff, diff * real64(total), remaining); if(diff > remaining) { diff = remaining; usedup = true; } remaining -= diff; // -- add that to the minimum for all the people before me diff = diff / real64(j); DebugLog_("Adjusted diff %Lf, remaining %Lf\n", diff, remaining); DebugLog_("People :"); for(uintn k = 0; k < j; ++k) { people[k].min += diff; DebugLog_(" %Lf", people[k].min); } DebugLog_("\n\n"); } if(!usedup) { remaining = remaining / real64(numpeople); DebugLog_("Average remaining %Lf\nPeople :", remaining); for(uintn k = 0; k < numpeople; ++k) { people[k].min += remaining; DebugLog_(" %Lf", people[k].min); } DebugLog_("\n"); } // -- sort the people back into their original order people.Sort<SByIndex>(); Log_("Case #%d:", i+1); for(uintn j = 0; j < numpeople; ++j) Log_(" %.6Lf", people[j].min * 100.0f); Log_("\n"); } // -- close the file fclose(fp); return 0; }
// ------------------------------------------------------------------------------------------------ // Iterate over all the possible multipliers for the given multiplicand // ------------------------------------------------------------------------------------------------ static void FindProducts(uintn a, uintn digitbits, CTable<uintn>& products) { uintn min = 1234 / a; uintn max = 9876 / a; // -- if a is a single digit, then the second operand needs to be 4 digits if(a < 10 && min < 1234) min = 1234; // -- if a is double digit, then the second operand needs to be 3 digits if(a >= 10) { if(min < 123) min = 123; if(max > 987) max = 987; } // -- if we've already ruled out the possibility of any results, just return if(max < min) return; // -- get the digits for the min, and then iterate up through the max uintn digits[4]; uintn curr = min - 1; for(uintn i = 0; i < 4; ++i) { digits[i] = curr % 10; curr /= 10; } // -- now iterate until we reach max curr = min - 1; while(curr <= max) { // -- look until we see a number with digits that don't overlap with the input flagn illegal = true; uintn currbits = digitbits; while(illegal) { // -- increment the ones digit ++digits[0]; if(digits[0] > 9) { digits[0] = 1; ++digits[1]; if(digits[1] > 9) { digits[1] = 1; ++digits[2]; if(digits[2] > 9) { digits[2] = 1; ++digits[3]; } } } // -- first update curr to be the new value curr = digits[0] + digits[1]*10 + digits[2]*100 + digits[3]*1000; if(curr > max) return; // -- then check the current digits to see if they are worth checking currbits = digitbits; illegal = false; for(uintn i = 0; i < 4 && !illegal; ++i) { // -- if we're zero and a higher digit is not zero (we're not a leading zero) // -- then this is an invalid number if(digits[i] == 0) { if(i+1 < 4 && digits[i+1] != 0) { illegal = true; break; } } else { // -- if this digit has already been done, keep looking if((currbits & (uintn(1) << digits[i])) != 0) { illegal = true; break; } // -- record this digit in the current bits currbits = currbits | uintn(1) << digits[i]; } } } uintn product = a * curr; // -- then look at each digit illegal = false; while(product > 0) { uintn digit = product % 10; product /= 10; // -- check to see if it's zero if(digit == 0) { illegal = true; break; } if((currbits & (uintn(1) << digit)) != 0) { illegal = true; break; } currbits = currbits | (uintn(1) << digit); } // -- if it's not illegal and we've found each digit from 1 to 9 if(!illegal && currbits == kAllNine) { product = a * curr; // -- look through the existing products, and make sure it's not already there uintn count = products.Count(); uintn i = 0; for(; i < count; ++i) { if(products[i] == product) break; } if(i == count) products.Grow(product); else CLog::Write("-repeat- "); CLog::Write(UintNFmt_ " x " UintNFmt_ " = " UintNFmt_ "\n", a, curr, product); } } }