Exemple #1
0
// ------------------------------------------------------------------------------------------------
// 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;
    }
}
Exemple #3
0
// ================================================================================================
// 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;
}
Exemple #4
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);
        }
    }
}