Skip to content

Instantly share code, notes, and snippets.

@donaldguy
Created June 26, 2013 20:00
Show Gist options
  • Save donaldguy/5871073 to your computer and use it in GitHub Desktop.
Save donaldguy/5871073 to your computer and use it in GitHub Desktop.
Semi-efficient heavy integer counter in C and Ruby for a code interview. The ruby is admittedly not very idiomatic (hence why I rewrote in C)
//
// main.c
// heavy_numbers
//
// Created by Donald Guy on 6/18/13.
// Copyright (c) 2013 Donald Guy. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef char int8;
/*
* Set BCD buffer to next multiple of 10 and return the number of carries required
*/
int set_to_nearest_ten(int8* digits, int num_digits) {
int num_carries = 1;
digits[num_digits - 1] = 0;
int i = num_digits - 2;
for (;;) {
digits[i] += 1;
if (digits[i] > 9) {
num_carries++;
digits[i--] = 0;
} else {
break;
}
}
return num_carries;
}
/*
* adjust left and right of inequality for the given number of carries, return number of digits
*/
int adjust_for_carries(int* left, int* right, int num_carries, int current_digits)
{
*left -= 9*num_carries - 1;
if (num_carries > current_digits) {
*right += 7;
return current_digits + 1;
} else {
return current_digits;
}
}
int solution(int a, int b) {
int total_digits = ceil(log10(b));
int current_digits = ceil(log10(a));
int current_value = a;
int8* digits = (int8*) malloc(total_digits * sizeof(int8));
int fill_index = total_digits - 1;
while (a > 0) {
digits[fill_index] = a % 10;
a /= 10;
fill_index--;
}
int left = 0;
for (int i = total_digits - current_digits; i < total_digits; i++) {
left += digits[i];
}
int right = current_digits * 7;
int total_heavy = 0;
while (current_value <= b) {
if (left > right) {
int distance_to_ten = 10 - digits[total_digits - 1];
// all values from here to next multiple of ten (noninclusive) are heavy
// so count them
total_heavy += distance_to_ten;
//move the loop control to match, but do so before we update digits
current_value += distance_to_ten;
// then update BCD buffer to that value and do bookeeping
int num_carries = set_to_nearest_ten(digits, total_digits);
//account for skipped values, if any
left += distance_to_ten - 1;
current_digits = adjust_for_carries(&left, &right, num_carries, current_digits);
} else {
current_value++;
if (digits[total_digits - 1] == 9) {
int num_carries = set_to_nearest_ten(digits, total_digits);
current_digits = adjust_for_carries(&left, &right, num_carries, current_digits);
} else {
digits[total_digits - 1] += 1;
left++;
}
}
}
if (current_value > b) {
int overshoot_amount = current_value - (b+1);
total_heavy -= overshoot_amount;
}
free(digits);
return total_heavy;
}
int main(int argc, const char * argv[])
{
printf("%d", solution(8675, 8689));
return 0;
}
# avg > 7
# sum / num > 7
# sum > 7*num
# left > right
# X[1-8] --> X[2-9] ---> left+1
# X[9]n --> (X+1)[0]n --> left-9*n+1
# [9]n --> 1[0]n --> left-9*n+1, right+7
def solution(a,b)
total_digits = Math.log(b,10).ceil
current_digits = Math.log(a,10).ceil
increment_left = b - a
digits = Array.new(total_digits)
fill_index = total_digits - 1
while a > 0
digits[fill_index] = a % 10
a /= 10
fill_index -= 1
end
left = digits.inject(&:+)
right = current_digits*7
total_heavy = 0
while increment_left >= 0
if left > right
distance_to_carry = 10 - digits[-1]
total_heavy += distance_to_carry
increment_left -= distance_to_carry
num_carries = do_carries(digits)
left += distance_to_carry - 1
left -= 9*num_carries - 1
if num_carries > current_digits
current_digits += 1
right += 7
end
else
increment_left -= 1
if digits[-1] == 9
num_carries = do_carries(digits)
left -= 9*num_carries - 1
if num_carries > current_digits
current_digits += 1
right += 7
end
else
left += 1
digits[-1] += 1
end
end
end
if increment_left < 0
total_heavy += increment_left + 1
end
total_heavy
end
def do_carries(digits)
num_carries = 1
digits[-1] = 0
index = digits.length - 2
loop do
digits[index] += 1
if digits[index] > 9
num_carries += 1
digits[index] = 0
index -= 1
else
break
end
end
num_carries
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment