Multi-Linear search problem in near constant time

Started by
24 comments, last by alvaro 14 years ago
Quote:Original post by Zipster
Again, could be more edge cases I'm missing.


This is quickly beginning to look like my original solution (check the OP). It solves in Log10(n) time and is pretty much the same math, just broken up a bit. I might be doing an unnecessary piece of algebra, as I have not combed over it for redundant operations to preserve the steps I took to arrive at it.

Edit: I was hoping to find a way to mathematically eliminate the logical statements (if statements) and reduce it to a formulaic form. Perhaps it isn't possible?
Advertisement
import mathdef digit(n, k):	return n/(10**(k)) % 10def right(n, k):	if k == 0:		return 0	return n % 10**(k)def left(n, k):	return n / 10**(k+1)	def ones(n):	ret = 0	for i in range(0, int(math.log10(n)+1)):		pow10 = 10**i		d = digit(n, i)		r = right(n, i)		l = left(n, i)				ret = ret + l*(pow10)					if d == 1: ret = ret + r + 1		if d >= 2: ret = ret + pow10		return ret


Ok, i am pretty sure this is right. In addition it does run in log10 time, so its still fast, but your right there are a few cases that ake this ugly. it may be possible to do better, but remember the number of 1's up to a number is not a natural mathematical concept, its a side effect of our way of concieving them, so don't wory about it being too pretty. thanks for the cool problem ... if this is wrong, let me know.

EDIT: Fixed mistake

[Edited by - ibebrett on March 31, 2010 9:59:17 PM]
Can't validate it right now, but check my algorithm in the OP and see if it matches yours. At first glance it looks very close.

Edit: Not the first brute force one, but the second one posted.
by the way

http://www2.research.att.com/~njas/sequences/?q=1,1,1,1,1,1,1,1,1,2,4,5,6,7,8,9&sort=0&fmt=0&language=english&go=Search

check this database out
we can validate against it.

and i fixed my solution above, i am 99% its right now (which i was before of course..)
Quote:Original post by ibebrett
by the way

http://www2.research.att.com/~njas/sequences/?q=1,1,1,1,1,1,1,1,1,2,4,5,6,7,8,9&sort=0&fmt=0&language=english&go=Search

check this database out
we can validate against it.

and i fixed my solution above, i am 99% its right now (which i was before of course..)


Yes, your solution looks identical to my solution (2nd code block in the op). I think it is probably the best one. The reason I was thinking there might be a mathematical solution is because this problem is based on probability. However, it does seem that the probability is spatial (relates to digit position) and cannot be solved as a set. Ah well, it was indeed fun to solve.
I wrote this program, which solves the original question pretty darn fast:
#include <iostream>typedef unsigned long long u64;u64 count_ones(u64 n) {  u64 result;  for (result = 0ull; n; n/=10) {    if (n%10==1)      result++;  }    return result;}u64 count_ones_in_range(u64 n, int changing) {  u64 range_size = 1ull;  for (int i=0; i<changing; ++i)    range_size*=10;    u64 prefix = n/range_size;    u64 previous_ones = count_ones(prefix);    return previous_ones*range_size + range_size*changing/10;}// returns count_ones_in_range(n, changing)u64 solve_range(u64 n, int changing, u64 count) {  u64 ones_in_range = count_ones_in_range(n, changing);    if (count + ones_in_range < n)    return ones_in_range;    u64 range_size = 1ull;  for (int i=0; i<changing; ++i)    range_size*=10;    if (count > n + range_size)    return ones_in_range;    if (changing) {    for (int i=0; i<10; ++i)      count += solve_range(n + range_size*i/10, changing-1, count);  }  else {    if (n==(count+ones_in_range))      std::cout << n << '\n';  }    return ones_in_range;}int main() {  solve_range(0,19,0);}


EDIT: The complete list of solutions for f(n)=n is this:
011999811999821999831999841999851999861999871999881999891999902000002000011599981159998215999831599984159998515999861599987159998815999891599990260000026000011319999835000000350000013519998135199982351999833519998435199985351999863519998735199988351999893519999035200000352000011174638255000000005000000015001999815001999825001999835001999845001999855001999865001999875001999885001999895001999905002000005002000015015999815015999825015999835015999845015999855015999865015999875015999885015999895015999905026000005026000015131999985350000005350000015351999815351999825351999835351999845351999855351999865351999875351999885351999895351999905352000005352000011111111110

This topic is closed to new replies.

Advertisement