Find all the 4 digit vampire numbers - algorithm

I am solving a problem to find out all the 4 digit Vampire numbers.
A Vampire Number v=x*y is defined as a number with 'n' even number of digits formed by multiplying a pair of 'n/2'-digit numbers (where the digits are taken from the original number in any order)x and y together. If v is a vampire number, then x&y and are called its "fangs."
Examples of vampire numbers are:
1. 1260=21*60
2. 1395=15*93
3. 1530=30*51
I have tried the brute force algorithm to combine different digits of a given number and multiply them together . But this method is highly inefficient and takes up a lot of time.
Is there a more efficient algorithmic solution to this problem?

Or you can use a property of vampire numbers described on this page (linked from Wikipedia) :
An important theoretical result found by Pete Hartley:
If x·y is a vampire number then x·y == x+y (mod 9)
Proof: Let mod be the binary modulo operator and d(x) the sum of the decimal
digits of x. It is well-known that d(x) mod 9 = x mod 9, for all x.
Assume x·y is a vampire. Then it contains the same digits as x and y,
and in particular d(x·y) = d(x)+d(y). This leads to:
(x·y) mod 9 = d(x·y) mod 9 = (d(x)+d(y)) mod 9 = (d(x) mod 9 + d(y) mod 9) mod 9
= (x mod 9 + y mod 9) mod 9 = (x+y) mod 9
The solutions to the congruence are (x mod 9, y mod 9) in {(0,0),
(2,2), (3,6), (5,8), (6,3), (8,5)}
So your code could look like this :
for(int i=18; i<100; i=i+9){ // 18 is the first multiple of 9 greater than 10
for(int j=i; j<100; j=j+9){ // Start at i because as #sh1 said it's useless to check both x*y and y*x
checkVampire(i,j);
}
}
for(int i=11; i<100; i=i+9){ // 11 is the first number greater than 10 which is = 2 mod 9
for(int j=i; j<100; j=j+9){
checkVampire(i,j);
}
}
for(int i=12; i<100; i=i+9){
for(int j=i+3; j<100; j=j+9){
checkVampire(i,j);
}
}
for(int i=14; i<100; i=i+9){
for(int j=i+3; j<100; j=j+9){
checkVampire(i,j);
}
}
// We don't do the last 2 loops, again for symmetry reasons
Since they are 40 elements in each of the sets like {(x mod 9, y mod 9) = (0,0); 10 <= x <= y <= 100}, you only do 4*40 = 160 iterations, when a brute-force gives you 10ˆ4 iterations. You can do even less operations if you take into account the >= 1000 constraint, for instance you can avoid checking if j < 1000/i.
Now you can easily scale up to find vampires with more than 4 digits =)

Iterate over all possible fangs (100 x 100 = 10000 possibilities), and find if their product has the same digits as the fangs.

Yet another brute force (C) version, with a free bubble sort to boot...
#include <stdio.h>
static inline void bubsort(int *p)
{ while (1)
{ int s = 0;
for (int i = 0; i < 3; ++i)
if (p[i] > p[i + 1])
{ s = 1;
int t = p[i]; p[i] = p[i + 1]; p[i + 1] = t;
}
if (!s) break;
}
}
int main()
{ for (int i = 10; i < 100; ++i)
for (int j = i; j < 100; ++j)
{ int p = i * j;
if (p < 1000) continue;
int xd[4];
xd[0] = i % 10;
xd[1] = i / 10;
xd[2] = j % 10;
xd[3] = j / 10;
bubsort(xd);
int x = xd[0] + xd[1] * 10 + xd[2] * 100 + xd[3] * 1000;
int yd[4];
yd[0] = p % 10;
yd[1] = (p / 10) % 10;
yd[2] = (p / 100) % 10;
yd[3] = (p / 1000);
bubsort(yd);
int y = yd[0] + yd[1] * 10 + yd[2] * 100 + yd[3] * 1000;
if (x == y)
printf("%2d * %2d = %4d\n", i, j, p);
}
return 0;
}
Runs pretty much instantaneously. Variable names aren't too descriptive, but should be pretty obvious...
The basic idea is to start with two potential fangs, break them down into digits, and sort the digits for easy comparison. Then we do the same with the product - break it down to digits and sort. Then we re-constitute two integers from the sorted digits, and if they're equal, we have a match.
Possible improvements: 1) start j at 1000 / i instead of i to avoid having to do if (p < 1000) ..., 2) maybe use insertion sort instead of bubble sort (but who's gonna notice those 2 extra swaps?), 3) use a real swap() implementation, 4) compare the arrays directly rather than building a synthetic integer out of them. Not sure any of those would make any measurable difference, though, unless you run it on a Commodore 64 or something...
Edit: Just out of curiosity, I took this version and generalized it a bit more to work for the 4, 6 and 8 digit cases - without any major optimization, it can find all the 8-digit vampire numbers in < 10 seconds...

This is an ugly hack (brute force, manual checking for permutations, unsafe buffer operations, produces dupes, etc.) but it does the job. Your new exercise is to improve it :P
Wikipedia claims that there are 7 vampire numbers which are 4 digits long. The full code has found them all, even some duplicates.
Edit: Here's a slightly better comparator function.
Edit 2: Here's a C++ version that uniques results (therefore it avoids duplicates) using an std::map (and stores the last occurrence of the particular vampire number along with its factors in it). It also meets the criterion that at least one of the factors should not end with 0, i. e. a number is not a vampire number if both of the multiplicands are divisible by then. This test looks for 6-digit vampire numbers and it does indeed find exactly 148 of them, in accordance with what Wikipedia sates.
The original code:
#include <stdio.h>
void getdigits(char buf[], int n)
{
while (n) {
*buf++ = n % 10;
n /= 10;
}
}
int is_vampire(const char n[4], const char i[2], const char j[2])
{
/* maybe a bit faster if unrolled manually */
if (i[0] == n[0]
&& i[1] == n[1]
&& j[0] == n[2]
&& j[1] == n[3])
return 1;
if (i[0] == n[1]
&& i[1] == n[0]
&& j[0] == n[2]
&& j[1] == n[3])
return 1;
if (i[0] == n[0]
&& i[1] == n[1]
&& j[0] == n[3]
&& j[1] == n[2])
return 1;
if (i[0] == n[1]
&& i[1] == n[0]
&& j[0] == n[3]
&& j[1] == n[2])
return 1;
// et cetera, the following 20 repetitions are redacted for clarity
// (this really should be a loop, shouldn't it?)
return 0;
}
int main()
{
for (int i = 10; i < 100; i++) {
for (int j = 10; j < 100; j++) {
int n = i * j;
if (n < 1000)
continue;
char ndigits[4];
getdigits(ndigits, n);
char idigits[2];
char jdigits[2];
getdigits(idigits, i);
getdigits(jdigits, j);
if (is_vampire(ndigits, idigits, jdigits))
printf("%d * %d = %d\n", i, j, n);
}
}
return 0;
}

I wouldn't have given up so easily on brute force. You have distinct set of numbers, 1000 to 9999 that you must run through. I would divide up the set into some number of subsets, and then spin up threads to handle each subset.
You could further divide the work be coming up with the various combinations of each number; IIRC my discrete math, you have 4*3*2 or 24 combinations for each number to try.
A producer / consumer approach might be worthwhile.

Iteration seems fine to me, since you only need to do this once to find all the values and you can just cache them afterwards. Python (3) version that takes about 1.5 seconds:
# just some setup
from itertools import product, permutations
dtoi = lambda *digits: int(''.join(str(digit) for digit in digits))
gen = ((dtoi(*digits), digits) for digits in product(range(10), repeat=4) if digits[0] != 0)
l = []
for val, digits in gen:
for check1, check2 in ((dtoi(*order[:2]), dtoi(*order[2:])) for order in permutations(digits) if order[0] > 0 and order[2] > 0):
if check1 * check2 == val:
l.append(val)
break
print(l)
Which will give you [1260, 1395, 1435, 1530, 1827, 2187, 6880]

EDIT: full brute force that weeds out identical X and Y values...
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Vampire {
public static void main(String[] args) {
for (int x = 10; x < 100; x++) {
String sx = String.valueOf(x);
for (int y = x; y < 100; y++) {
int v = x * y;
String sy = String.valueOf(y);
String sv = String.valueOf(v);
if (sortVampire(sx + sy).equals(sortVampire(sv))) {
System.out.printf("%d * %d = %d%n", x, y, v);
}
}
}
}
private static List<Character> sortVampire(String v) {
List<Character> vc = new ArrayList<Character>();
for (int j = 0; j < v.length(); j++) {
vc.add(v.charAt(j));
}
Collections.sort(vc);
return vc;
}
}

Brute force version in C# with LINQ:
class VampireNumbers
{
static IEnumerable<int> numberToDigits(int number)
{
while(number > 0)
{
yield return number % 10;
number /= 10;
}
}
static bool isVampire(int first, int second, int result)
{
var resultDigits = numberToDigits(result).OrderBy(x => x);
var vampireDigits = numberToDigits(first)
.Concat(numberToDigits(second))
.OrderBy(x => x);
return resultDigits.SequenceEqual(vampireDigits);
}
static void Main(string[] args)
{
var vampires = from fang1 in Enumerable.Range(10, 89)
from fang2 in Enumerable.Range(10, 89)
where fang1 < fang2
&& isVampire(fang1, fang2, fang1 * fang2)
select new { fang1, fang2 };
foreach(var vampire in vampires)
{
Console.WriteLine(vampire.fang1 * vampire.fang2
+ " = "
+ vampire.fang1
+ " * "
+ vampire.fang2);
}
}
}

Similar to someone mentioned above, my method is to first find all permutations of a number, then split them in half to form two 2-digit numbers, and test if their product equal to the original number.
Another interesting discussion above is how many permutations a number can have. Here is my opinion:
(1) a number whose four digitals are the same has 1 permutation;
(2) a number who has only two different digits has 6 permutations (it doesn't matter if it contains zeros, because we don't care after permutation if it is still a 4-digit number);
(3) a number who has three different digits has 12 permutations;
(4) a number with all four different digits has 24 permutations.
public class VampireNumber {
// method to find all permutations of a 4-digit number
public static void permuta(String x, String s, int v)
{for(int i = 0; i < s.length(); i++)
{permuta( x + s.charAt(i), s.substring(0,i) + s.substring(i+1), v);
if (s.length() == 1)
{x = x + s;
int leftpart = Integer.parseInt(x.substring(0,2));
int rightpart = Integer.parseInt(x.substring(2));
if (leftpart*rightpart == v)
{System.out.println("Vampir = " + v);
}
}
}
}
public static void main(String[] args){
for (int i = 1000; i < 10000; i++) {
permuta("", Integer.toString(i), i); //convert the integer to a string
}
}
}

The approach I would try would be to loop through each number in [1000, 9999], and test if any permutation of its digits (split in the middle) multiplied to make it.
This will require (9999 - 1000) * 24 = 215,976 tests, which should execute acceptably fast on a modern machine.
I would definitely store the digits separately, so you can avoid having to do something like a bunch of division to extract the digits from a single integer.
If you write your code such that you're only ever doing integer addition and multiplication (and maybe the occasional division to carry), it should be pretty fast. You could further increase the speed by skipping two-digit pairs which "obviously" won't work - e.g., ones with leading zeros (note that the largest product than can be produced by a one digit number and a two digit number is 9 * 99, or 891).
Also note that this approach is embarassingly parallel (http://en.wikipedia.org/wiki/Embarrassingly_parallel), so if you really need to speed it up even more then you should look into testing the numbers in separate threads.

<?php
for ($i = 10; $i <= 99; $j++) {
// Extract digits
$digits = str_split($i);
// Loop through 2nd number
for ($j = 10; $j <= 99; $j++) {
// Extract digits
$j_digits = str_split($j);
$digits[2] = $j_digits[0];
$digits[3] = $j_digits[1];
$product = $i * $j;
$product_digits = str_split($product);
// check if fangs
$inc = 0;
while (in_array($digits[$inc], $product_digits)) {
// Remove digit from product table
/// So AAAA -> doesnt match ABCD
unset($product_digits[$array_serach($digits[$inc], $product_digits)]);
$inc++;
// If reached 4 -> vampire number
if ($inc == 4) {
$vampire[] = $product;
break;
}
}
}
}
// Print results
print_r($vampire);
?>
Took less than a second on PHP. couldn't even tell it had to run 8100 computations... computers are fast!
Results:
Gives you all the 4 digits plus some are repeated. You can further process the data and remove duplicates.

It seems to me that to perform the fewest possible tests without relying on any particularly abstract insights, you probably want to iterate over the fangs and cull any obviously pointless candidates.
For example, since x*y == y*x about half your search space can be eliminated by only evaluating cases where y > x. If the largest two-digit fang is 99 then the smallest which can make a four-digit number is 11, so don't start lower than 11.
EDIT:
OK, throwing everything I thought of into the mix (even though it looks silly against the leading solution).
for (x = 11; x < 100; x++)
{
/* start y either at x, or if x is too small then 1000 / x */
for (y = (x * x < 1000 ? 1000 / x : x); y < 100; y++)
{
int p = x * y;
/* if sum of digits in product is != sum of digits in x+y, then skip */
if ((p - (x + y)) % 9 != 0)
continue;
if (is_vampire(p, x, y))
printf("%d\n", p);
}
}
and the test, since I haven't seen anyone use a histogram, yet:
int is_vampire(int p, int x, int y)
{
int h[10] = { 0 };
int i;
for (i = 0; i < 4; i++)
{
h[p % 10]++;
p /= 10;
}
for (i = 0; i < 2; i++)
{
h[x % 10]--;
h[y % 10]--;
x /= 10;
y /= 10;
}
for (i = 0; i < 10; i++)
if (h[i] != 0)
return 0;
return 1;
}

1260 1395 1435 1530 1827 2187 6880 is vampire
I am new to programming... But there are only 12 combinations in finding all 4-digit vampire numbers. My poor answer is:
public class VampNo {
public static void main(String[] args) {
for(int i = 1000; i < 10000; i++) {
int a = i/1000;
int b = i/100%10;
int c = i/10%10;
int d = i%10;
if((a * 10 + b) * (c * 10 + d) == i || (b * 10 + a) * (d * 10 + c) == i ||
(a * 10 + d) * (b * 10 + c) == i || (d * 10 + a) * (c * 10 + b) == i ||
(a * 10 + c) * (b * 10 + d) == i || (c * 10 + a) * (d * 10 + b) == i ||
(a * 10 + b) * (d * 10 + c) == i || (b * 10 + a) * (c * 10 + d) == i ||
(b * 10 + c) * (d * 10 + a) == i || (c * 10 + b) * (a * 10 + d) == i ||
(a * 10 + c) * (d * 10 + b) == i || (c * 10 + a) * (b * 10 + d) == i)
System.out.println(i + " is vampire");
}
}
}
The main task now is to simplify boolean expression in If() block

I've edited Owlstead's algorithm a bit to make it more understandable to Java beginners/learners.
import java.util.Arrays;
public class Vampire {
public static void main(String[] args) {
for (int x = 10; x < 100; x++) {
String sx = Integer.toString(x);
for (int y = x; y < 100; y++) {
int v = x * y;
String sy = Integer.toString(y);
String sv = Integer.toString(v);
if( Arrays.equals(sortVampire(sx + sy), sortVampire(sv)))
System.out.printf("%d * %d = %d%n", x, y, v);
}
}
}
private static char[] sortVampire (String v){
char[] sortedArray = v.toCharArray();
Arrays.sort(sortedArray);
return sortedArray;
}
}

This python code run very fast (O(n2))
result = []
for i in range(10,100):
for j in range(10, 100):
list1 = []
list2 = []
k = i * j
if k < 1000 or k > 10000:
continue
else:
for item in str(i):
list1.append(item)
for item in str(j):
list1.append(item)
for item in str(k):
list2.append(item)
flag = 1
for each in list1:
if each not in list2:
flag = 0
else:
list2.remove(each)
for each in list2:
if each not in list1:
flag = 0
if flag == 1:
if k not in result:
result.append(k)
for each in result:
print(each)

And here is my code. To generate zombie numbers we need to use Random class :)
import java.io.PrintStream;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
class VampireNumbers {
static PrintStream p = System.out;
private static Set<Integer> findVampireNumber() {
Set<Integer> vampireSet = new HashSet<Integer>();
for (int y = 1000; y <= 9999; y++) {
char[] numbersSeparately = ("" + y).toCharArray();
int numberOfDigits = numbersSeparately.length;
for (int i = 0; i < numberOfDigits; i++) {
for (int j = 0; j < numberOfDigits; j++) {
if (i != j) {
int value1 = Integer.valueOf("" + numbersSeparately[i] + numbersSeparately[j]);
int ki = -1;
for (int k = 0; k < numberOfDigits; k++) {
if (k != i && k != j) {
ki = k;
}
}
int kj = -1;
for (int t = 0; t < numberOfDigits; t++) {
if (t != i && t != j && t != ki) {
kj = t;
}
}
int value21 = Integer.valueOf("" + numbersSeparately[ki] + numbersSeparately[kj]);
int value22 = Integer.valueOf("" + numbersSeparately[kj] + numbersSeparately[ki]);
if (value1 * value21 == y && !(numbersSeparately[j] == 0 && numbersSeparately[kj] == 0)
|| value1 * value22 == y
&& !(numbersSeparately[j] == 0 && numbersSeparately[ki] == 0)) {
vampireSet.add(y);
}
}
}
}
}
return vampireSet;
}
public static void main(String[] args) {
Set<Integer> vampireSet = findVampireNumber();
Iterator<Integer> i = vampireSet.iterator();
int number = 1;
while (i.hasNext()) {
p.println(number + ": " + i.next());
number++;
}
}
}

Related

Get three-digit numbers where the sum of factorials of the digits equals to the number

I am reading combinatorial book for school and have to do some exercises, this is one of them:
Write a computer program to determine whether there is a three-digit integer abc (= 100a + 10b + c) where abc = a! + b! + c!.
My attempt is below.
Can someone propose a better (faster) algorithm for this task?
int power(int n)
{
int sum=1;
for(int i=2;i<=n;i++){
sum*=i;
}
return sum;
}
void compute()
{
int abc;
int powa,powb,powc;
for(int a=1;a<100;a++){
for(int b=1;b<100;b++){
for(int c=1;c<100;c++){
abc=(100*a)+(10*b)+c;
powa=power(a);
powb=power(b);
powc=power(c);
if(abc==(powa+powb+powc)){
cout<<"There is ,nums are :"<<a<<","<<b<<","<<c<<endl;
}
}
}
}
}
int main()
{
compute();
return 0;
}
for (var n = 0; n < 1000; n++)
{
var a = (n / 100);
var b = (n / 10) % 10;
var c = n % 10;
var m = a! + b! + c!;
if (m == n)
{
Console.WriteLine(n);
}
}
Maybe start with 100 if you don't want to consider leading zeros. Or this way.
for (var a = 0; a < 10; a++)
{
for (var b = 0; b < 10; b++)
{
for (var c = 0; c < 10; c++)
{
var n = 100 * a + 10 * b + c;
var m = a! + b! + c!;
if (m == n)
{
Console.WriteLine(n);
}
}
}
}
Again maybe skip zeros if you don't want leading zeros. You may also be able to exit loops early if you determine that m will always be larger than n. For example a, b and c can not become larger than 6 because 7! is larger than 999.
We have 900 possible numbers at the beginning. Observing the rules we can notice the following:
7!, 8! and 9! are bigger than 999, so they cannot be used. This gets us down to 294 possible numbers.
0!, 1!, 2!, 3! and !4 are all smaller than 25. This means that at least one of the three digits you use will have to be five or bigger. This reduces it down to 194 possible numbers.
Now that we've eliminated a big number of cases on paper, we need to check them all. Instead of calculating the factorials all the time we calculate them once for every digit 0-6 and save them in an array.
Then for every combination three digits 0-6 (with the first one being 1) where at least one
is bigger than 4, we check if it fits the condition a!+b!+c!=a*100+b*10+c.
There might be some additional ways to optimize it, but even this is overkill considering you only have 3 digits (which is a very small number of possible cases).
int factorials[7];
int factorial(int n)
{
if(n<2)return n;
else return n*factorial(n-1);
}
void check(int a, int b, int c)
{
if((a>4 || b>4 || c>4) && factorials[a]+factorials[b]+factorials[c]==a*100+b*10+c)
cout<<"There is, nums are : "<<a<<","<<b<<","<<c<<endl;
}
int main()
{
for(int i=0;i<7;i++)factorials[i]=factorial(i);
for(int a=1;a<7;a++)
for(int b=0;b<7;b++)
for(int c=0;c<7;c++)check(a,b,c);
return 0;
}

Fast code to determine if any two subsets of columns have the same sum

For a given n and m I iterate over all n by m partial circulant matrices with entries that are either 0 or 1. I want to find if there is a matrix such that there are no two subsets of the columns that give the same sum. Here when we add columns we just do it elementwise. My current code uses constraint programming via ortools. However it is not as fast I would like. For n = 7 and m = 12 it takes over 3 minutes and for n = 10, m = 18 it doesn't terminate even though there are only 2^18 = 262144 different matrices to consider. Here is my code.
from scipy.linalg import circulant
import numpy as np
import itertools
from ortools.constraint_solver import pywrapcp as cs
n = 7
m = 12
def isdetecting(matrix):
X = np.array([solver.IntVar(values) for i in range(matrix.shape[1])])
X1 = X.tolist()
for row in matrix:
x = X[row].tolist()
solver.Add(solver.Sum(x) == 0)
db = solver.Phase(X1, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)
solver.NewSearch(db)
count = 0
while (solver.NextSolution() and count < 2):
solution = [x.Value() for x in X1]
count += 1
solver.EndSearch()
if (count < 2):
return True
values = [-1,0,1]
solver = cs.Solver("scip")
for row in itertools.product([0,1],repeat = m):
M = np.array(circulant(row)[0:n], dtype=bool)
if isdetecting(M):
print M.astype(int)
break
Can this problem be solved fast enough so that n = 10, m = 18 can be solved?
One problem is that you are declaring the "solver" variable globally and it seems to confuse or-tools to reuse it many times. When moving it inside "isdetecting", then the (7,12) problem is solved much faster, in about 7 seconds (compared to 2:51 minutes for the original model). I haven't checked it for the larger problem, though.
Also, it might be good idea to test different labelings (instead of solver.INT_VAR_DEFAULT and solver.INT_VALUE_DEFAULT), though binary value tend to be not very sensitive to different labelings. See the code for another labeling.
def isdetecting(matrix):
solver = cs.Solver("scip") # <----
X = np.array([solver.IntVar(values) for i in range(matrix.shape[1])])
X1 = X.tolist()
for row in matrix:
x = X[row].tolist()
solver.Add(solver.Sum(x) == 0)
# db = solver.Phase(X1, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)
db = solver.Phase(X1, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_CENTER_VALUE)
solver.NewSearch(db)
count = 0
while (solver.NextSolution() and count < 2):
solution = [x.Value() for x in X1]
count += 1
solver.EndSearch()
if (count < 2):
print "FOUND"
return True
Edit: Here are constraints to remove the all-0 solutions as mentioned in the comments. What I know of, it require a separate list. It now takes a little longer (10.4s vs 7s).
X1Abs = [solver.IntVar(values, 'X1Abs[%i]' % i) for i in range(X1_len)]
for i in range(X1_len):
solver.Add(X1Abs[i] == abs(X1[i]))
solver.Add(solver.Sum(X1Abs) > 0)
Something like this is what I had in mind. I'd estimate the running time for command line parameters 10 18 at less than 8 hours on my machine.
public class Search {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int m = Integer.parseInt(args[1]);
int row = search(n, m);
if (row >= 0) {
printRow(m, row);
}
}
private static int search(int n, int m) {
if (n < 0 || m < n || m >= 31 || powOverflows(m + 1, n)) {
throw new IllegalArgumentException();
}
long[] column = new long[m];
long[] sums = new long[1 << m];
int row = 1 << m;
while (row-- > 0) {
System.err.println(row);
for (int j = 0; j < m; j++) {
column[j] = 0;
for (int i = 0; i < n; i++) {
column[j] = (column[j] * (m + 1)) + ((row >> ((i + j) % m)) & 1);
}
}
for (int subset = 0; subset < (1 << m); subset++) {
long sum = 0;
for (int j = 0; j < m; j++) {
if (((subset >> j) & 1) == 1) {
sum += column[j];
}
}
sums[subset] = sum;
}
java.util.Arrays.sort(sums);
boolean duplicate = false;
for (int k = 1; k < (1 << m); k++) {
if (sums[k - 1] == sums[k]) {
duplicate = true;
break;
}
}
if (!duplicate) {
break;
}
}
return row;
}
private static boolean powOverflows(long b, int e) {
if (b <= 0 || e < 0) {
throw new IllegalArgumentException();
}
if (e == 0) {
return false;
}
long max = Long.MAX_VALUE;
while (e > 1) {
if (b > Integer.MAX_VALUE) {
return true;
}
if ((e & 1) == 1) {
max /= b;
}
b *= b;
e >>= 1;
}
return b > max;
}
private static void printRow(int m, int row) {
for (int j = 0; j < m; j++) {
System.out.print((row >> j) & 1);
}
System.out.println();
}
}

Discover long patterns

Given a sorted list of numbers, I would like to find the longest subsequence where the differences between successive elements are geometrically increasing. So if the list is
1, 2, 3, 4, 7, 15, 27, 30, 31, 81
then the subsequence is 1, 3, 7, 15, 31. Alternatively consider 1, 2, 5, 6, 11, 15, 23, 41, 47 which has subsequence 5, 11, 23, 47 with a = 3 and k = 2.
Can this be solved in O(n2) time? Where n is the length of the list.
I am interested both in the general case where the progression of differences is ak, ak2, ak3, etc., where both a and k are integers, and in the special case where a = 1, so the progression of difference is k, k2, k3, etc.
Update
I have made an improvement of the algorithm that it takes an average of O(M + N^2) and memory needs of O(M+N). Mainly is the same that the protocol described below, but to calculate the possible factors A,K for ech diference D, I preload a table. This table takes less than a second to be constructed for M=10^7.
I have made a C implementation that takes less than 10minutes to solve N=10^5 diferent random integer elements.
Here is the source code in C: To execute just do: gcc -O3 -o findgeo findgeo.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include <time.h>
struct Factor {
int a;
int k;
struct Factor *next;
};
struct Factor *factors = 0;
int factorsL=0;
void ConstructFactors(int R) {
int a,k,C;
int R2;
struct Factor *f;
float seconds;
clock_t end;
clock_t start = clock();
if (factors) free(factors);
factors = malloc (sizeof(struct Factor) *((R>>1) + 1));
R2 = R>>1 ;
for (a=0;a<=R2;a++) {
factors[a].a= a;
factors[a].k=1;
factors[a].next=NULL;
}
factorsL=R2+1;
R2 = floor(sqrt(R));
for (k=2; k<=R2; k++) {
a=1;
C=a*k*(k+1);
while (C<R) {
C >>= 1;
f=malloc(sizeof(struct Factor));
*f=factors[C];
factors[C].a=a;
factors[C].k=k;
factors[C].next=f;
a++;
C=a*k*(k+1);
}
}
end = clock();
seconds = (float)(end - start) / CLOCKS_PER_SEC;
printf("Construct Table: %f\n",seconds);
}
void DestructFactors() {
int i;
struct Factor *f;
for (i=0;i<factorsL;i++) {
while (factors[i].next) {
f=factors[i].next->next;
free(factors[i].next);
factors[i].next=f;
}
}
free(factors);
factors=NULL;
factorsL=0;
}
int ipow(int base, int exp)
{
int result = 1;
while (exp)
{
if (exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
void findGeo(int **bestSolution, int *bestSolutionL,int *Arr, int L) {
int i,j,D;
int mustExistToBeBetter;
int R=Arr[L-1]-Arr[0];
int *possibleSolution;
int possibleSolutionL=0;
int exp;
int NextVal;
int idx;
int kMax,aMax;
float seconds;
clock_t end;
clock_t start = clock();
kMax = floor(sqrt(R));
aMax = floor(R/2);
ConstructFactors(R);
*bestSolutionL=2;
*bestSolution=malloc(0);
possibleSolution = malloc(sizeof(int)*(R+1));
struct Factor *f;
int *H=malloc(sizeof(int)*(R+1));
memset(H,0, sizeof(int)*(R+1));
for (i=0;i<L;i++) {
H[ Arr[i]-Arr[0] ]=1;
}
for (i=0; i<L-2;i++) {
for (j=i+2; j<L; j++) {
D=Arr[j]-Arr[i];
if (D & 1) continue;
f = factors + (D >>1);
while (f) {
idx=Arr[i] + f->a * f->k - Arr[0];
if ((f->k <= kMax)&& (f->a<aMax)&&(idx<=R)&&H[idx]) {
if (f->k ==1) {
mustExistToBeBetter = Arr[i] + f->a * (*bestSolutionL);
} else {
mustExistToBeBetter = Arr[i] + f->a * f->k * (ipow(f->k,*bestSolutionL) - 1)/(f->k-1);
}
if (mustExistToBeBetter< Arr[L-1]+1) {
idx= floor(mustExistToBeBetter - Arr[0]);
} else {
idx = R+1;
}
if ((idx<=R)&&H[idx]) {
possibleSolution[0]=Arr[i];
possibleSolution[1]=Arr[i] + f->a*f->k;
possibleSolution[2]=Arr[j];
possibleSolutionL=3;
exp = f->k * f->k * f->k;
NextVal = Arr[j] + f->a * exp;
idx=NextVal - Arr[0];
while ( (idx<=R) && H[idx]) {
possibleSolution[possibleSolutionL]=NextVal;
possibleSolutionL++;
exp = exp * f->k;
NextVal = NextVal + f->a * exp;
idx=NextVal - Arr[0];
}
if (possibleSolutionL > *bestSolutionL) {
free(*bestSolution);
*bestSolution = possibleSolution;
possibleSolution = malloc(sizeof(int)*(R+1));
*bestSolutionL=possibleSolutionL;
kMax= floor( pow (R, 1/ (*bestSolutionL) ));
aMax= floor(R / (*bestSolutionL));
}
}
}
f=f->next;
}
}
}
if (*bestSolutionL == 2) {
free(*bestSolution);
possibleSolutionL=0;
for (i=0; (i<2)&&(i<L); i++ ) {
possibleSolution[possibleSolutionL]=Arr[i];
possibleSolutionL++;
}
*bestSolution = possibleSolution;
*bestSolutionL=possibleSolutionL;
} else {
free(possibleSolution);
}
DestructFactors();
free(H);
end = clock();
seconds = (float)(end - start) / CLOCKS_PER_SEC;
printf("findGeo: %f\n",seconds);
}
int compareInt (const void * a, const void * b)
{
return *(int *)a - *(int *)b;
}
int main(void) {
int N=100000;
int R=10000000;
int *A = malloc(sizeof(int)*N);
int *Sol;
int SolL;
int i;
int *S=malloc(sizeof(int)*R);
for (i=0;i<R;i++) S[i]=i+1;
for (i=0;i<N;i++) {
int r = rand() % (R-i);
A[i]=S[r];
S[r]=S[R-i-1];
}
free(S);
qsort(A,N,sizeof(int),compareInt);
/*
int step = floor(R/N);
A[0]=1;
for (i=1;i<N;i++) {
A[i]=A[i-1]+step;
}
*/
findGeo(&Sol,&SolL,A,N);
printf("[");
for (i=0;i<SolL;i++) {
if (i>0) printf(",");
printf("%d",Sol[i]);
}
printf("]\n");
printf("Size: %d\n",SolL);
free(Sol);
free(A);
return EXIT_SUCCESS;
}
Demostration
I will try to demonstrate that the algorithm that I proposed is in average for an equally distributed random sequence. I’m not a mathematician and I am not used to do this kind of demonstrations, so please fill free to correct me any error that you can see.
There are 4 indented loops, the two firsts are the N^2 factor. The M is for the calculation of the possible factors table).
The third loop is executed only once in average for each pair. You can see this checking the size of the pre-calculated factors table. It’s size is M when N->inf. So the average steps for each pair is M/M=1.
So the proof happens to check that the forth loop. (The one that traverses the good made sequences is executed less that or equal O(N^2) for all the pairs.
To demonstrate that, I will consider two cases: one where M>>N and other where M ~= N. Where M is the maximum difference of the initial array: M= S(n)-S(1).
For the first case, (M>>N) the probability to find a coincidence is p=N/M. To start a sequence, it must coincide the second and the b+1 element where b is the length of the best sequence until now. So the loop will enter times. And the average length of this series (supposing an infinite series) is . So the total number of times that the loop will be executed is . And this is close to 0 when M>>N. The problem here is when M~=N.
Now lets consider this case where M~=N. Lets consider that b is the best sequence length until now. For the case A=k=1, then the sequence must start before N-b, so the number of sequences will be N-b, and the times that will go for the loop will be a maximum of (N-b)*b.
For A>1 and k=1 we can extrapolate to where d is M/N (the average distance between numbers). If we add for all A’s from 1 to dN/b then we see a top limit of:
For the cases where k>=2, we see that the sequence must start before , So the loop will enter an average of and adding for all As from 1 to dN/k^b, it gives a limit of
Here, the worst case is when b is minimum. Because we are considering minimum series, lets consider a very worst case of b= 2 so the number of passes for the 4th loop for a given k will be less than
.
And if we add all k’s from 2 to infinite will be:
So adding all the passes for k=1 and k>=2, we have a maximum of:
Note that d=M/N=1/p.
So we have two limits, One that goes to infinite when d=1/p=M/N goes to 1 and other that goes to infinite when d goes to infinite. So our limit is the minimum of both, and the worst case is when both equetions cross. So if we solve the equation:
we see that the maximum is when d=1.353
So it is demonstrated that the forth loops will be processed less than 1.55N^2 times in total.
Of course, this is for the average case. For the worst case I am not able to find a way to generate series whose forth loop are higher than O(N^2), and I strongly believe that they does not exist, but I am not a mathematician to prove it.
Old Answer
Here is a solution in average of O((n^2)*cube_root(M)) where M is the difference between the first and last element of the array. And memory requirements of O(M+N).
1.- Construct an array H of length M so that M[i - S[0]]=true if i exists in the initial array and false if it does not exist.
2.- For each pair in the array S[j], S[i] do:
2.1 Check if it can be the first and third elements of a possible solution. To do so, calculate all possible A,K pairs that meet the equation S(i) = S(j) + AK + AK^2. Check this SO question to see how to solve this problem. And check that exist the second element: S[i]+ A*K
2.2 Check also that exist the element one position further that the best solution that we have. For example, if the best solution that we have until now is 4 elements long then check that exist the element A[j] + AK + AK^2 + AK^3 + AK^4
2.3 If 2.1 and 2.2 are true, then iterate how long is this series and set as the bestSolution until now is is longer that the last.
Here is the code in javascript:
function getAKs(A) {
if (A / 2 != Math.floor(A / 2)) return [];
var solution = [];
var i;
var SR3 = Math.pow(A, 1 / 3);
for (i = 1; i <= SR3; i++) {
var B, C;
C = i;
B = A / (C * (C + 1));
if (B == Math.floor(B)) {
solution.push([B, C]);
}
B = i;
C = (-1 + Math.sqrt(1 + 4 * A / B)) / 2;
if (C == Math.floor(C)) {
solution.push([B, C]);
}
}
return solution;
}
function getBestGeometricSequence(S) {
var i, j, k;
var bestSolution = [];
var H = Array(S[S.length-1]-S[0]);
for (i = 0; i < S.length; i++) H[S[i] - S[0]] = true;
for (i = 0; i < S.length; i++) {
for (j = 0; j < i; j++) {
var PossibleAKs = getAKs(S[i] - S[j]);
for (k = 0; k < PossibleAKs.length; k++) {
var A = PossibleAKs[k][0];
var K = PossibleAKs[k][17];
var mustExistToBeBetter;
if (K==1) {
mustExistToBeBetter = S[j] + A * bestSolution.length;
} else {
mustExistToBeBetter = S[j] + A * K * (Math.pow(K,bestSolution.length) - 1)/(K-1);
}
if ((H[S[j] + A * K - S[0]]) && (H[mustExistToBeBetter - S[0]])) {
var possibleSolution=[S[j],S[j] + A * K,S[i]];
exp = K * K * K;
var NextVal = S[i] + A * exp;
while (H[NextVal - S[0]] === true) {
possibleSolution.push(NextVal);
exp = exp * K;
NextVal = NextVal + A * exp;
}
if (possibleSolution.length > bestSolution.length) {
bestSolution = possibleSolution;
}
}
}
}
}
return bestSolution;
}
//var A= [ 1, 2, 3,5,7, 15, 27, 30,31, 81];
var A=[];
for (i=1;i<=3000;i++) {
A.push(i);
}
var sol=getBestGeometricSequence(A);
$("#result").html(JSON.stringify(sol));
You can check the code here: http://jsfiddle.net/6yHyR/1/
I maintain the other solution because I believe that it is still better when M is very big compared to N.
Just to start with something, here is a simple solution in JavaScript:
var input = [0.7, 1, 2, 3, 4, 7, 15, 27, 30, 31, 81],
output = [], indexes, values, i, index, value, i_max_length,
i1, i2, i3, j1, j2, j3, difference12a, difference23a, difference12b, difference23b,
scale_factor, common_ratio_a, common_ratio_b, common_ratio_c,
error, EPSILON = 1e-9, common_ratio_is_integer,
resultDiv = $("#result");
for (i1 = 0; i1 < input.length - 2; ++i1) {
for (i2 = i1 + 1; i2 < input.length - 1; ++i2) {
scale_factor = difference12a = input[i2] - input[i1];
for (i3 = i2 + 1; i3 < input.length; ++i3) {
difference23a = input[i3] - input[i2];
common_ratio_1a = difference23a / difference12a;
common_ratio_2a = Math.round(common_ratio_1a);
error = Math.abs((common_ratio_2a - common_ratio_1a) / common_ratio_1a);
common_ratio_is_integer = error < EPSILON;
if (common_ratio_2a > 1 && common_ratio_is_integer) {
indexes = [i1, i2, i3];
j1 = i2;
j2 = i3
difference12b = difference23a;
for (j3 = j2 + 1; j3 < input.length; ++j3) {
difference23b = input[j3] - input[j2];
common_ratio_1b = difference23b / difference12b;
common_ratio_2b = Math.round(common_ratio_1b);
error = Math.abs((common_ratio_2b - common_ratio_1b) / common_ratio_1b);
common_ratio_is_integer = error < EPSILON;
if (common_ratio_is_integer && common_ratio_2a === common_ratio_2b) {
indexes.push(j3);
j1 = j2;
j2 = j3
difference12b = difference23b;
}
}
values = [];
for (i = 0; i < indexes.length; ++i) {
index = indexes[i];
value = input[index];
values.push(value);
}
output.push(values);
}
}
}
}
if (output !== []) {
i_max_length = 0;
for (i = 1; i < output.length; ++i) {
if (output[i_max_length].length < output[i].length)
i_max_length = i;
}
for (i = 0; i < output.length; ++i) {
if (output[i_max_length].length == output[i].length)
resultDiv.append("<p>[" + output[i] + "]</p>");
}
}
Output:
[1, 3, 7, 15, 31]
I find the first three items of every subsequence candidate, calculate the scale factor and the common ratio from them, and if the common ratio is integer, then I iterate over the remaining elements after the third one, and add those to the subsequence, which fit into the geometric progression defined by the first three items. As a last step, I select the sebsequence/s which has/have the largest length.
In fact it is exactly the same question as Longest equally-spaced subsequence, you just have to consider the logarithm of your data. If the sequence is a, ak, ak^2, ak^3, the logarithmique value is ln(a), ln(a) + ln(k), ln(a)+2ln(k), ln(a)+3ln(k), so it is equally spaced. The opposite is of course true. There is a lot of different code in the question above.
I don't think the special case a=1 can be resolved more efficiently than an adaptation from an algorithm above.
Here is my solution in Javascript. It should be close to O(n^2) except may be in some pathological cases.
function bsearch(Arr,Val, left,right) {
if (left == right) return left;
var m=Math.floor((left + right) /2);
if (Val <= Arr[m]) {
return bsearch(Arr,Val,left,m);
} else {
return bsearch(Arr,Val,m+1,right);
}
}
function findLongestGeometricSequence(S) {
var bestSolution=[];
var i,j,k;
var H={};
for (i=0;i<S.length;i++) H[S[i]]=true;
for (i=0;i<S.length;i++) {
for (j=0;j<i;j++) {
for (k=j+1;k<i;) {
var possibleSolution=[S[j],S[k],S[i]];
var K = (S[i] - S[k]) / (S[k] - S[j]);
var A = (S[k] - S[j]) * (S[k] - S[j]) / (S[i] - S[k]);
if ((Math.floor(K) == K) && (Math.floor(A)==A)) {
exp= K*K*K;
var NextVal= S[i] + A * exp;
while (H[NextVal] === true) {
possibleSolution.push(NextVal);
exp = exp * K;
NextVal= NextVal + A * exp;
}
if (possibleSolution.length > bestSolution.length)
bestSolution=possibleSolution;
K--;
} else {
K=Math.floor(K);
}
if (K>0) {
var NextPossibleMidValue= (S[i] + K*S[j]) / (K +1);
k++;
if (S[k]<NextPossibleMidValue) {
k=bsearch(S,NextPossibleMidValue, k+1, i);
}
} else {
k=i;
}
}
}
}
return bestSolution;
}
function Run() {
var MyS= [0.7, 1, 2, 3, 4, 5,6,7, 15, 27, 30,31, 81];
var sol = findLongestGeometricSequence(MyS);
alert(JSON.stringify(sol));
}
Small Explanation
If we take 3 numbers of the array S(j) < S(k) < S(i) then you can calculate a and k so that: S(k) = S(j) + a*k and S(i) = S(k) + a*k^2 (2 equations and 2 incognits). With that in mind, you can check if exist a number in the array that is S(next) = S(i) + a*k^3. If that is the case, then continue checknng for S(next2) = S(next) + a*k^4 and so on.
This would be a O(n^3) solution, but you can hava advantage that k must be integer in order to limit the S(k) points selected.
In case that a is known, then you can calculate a(k) and you need to check only one number in the third loop, so this case will be clearly a O(n^2).
I think this task is related with not so long ago posted Longest equally-spaced subsequence. I've just modified my algorithm in Python a little bit:
from math import sqrt
def add_precalc(precalc, end, (a, k), count, res, N):
if end + a * k ** res[1]["count"] > N: return
x = end + a * k ** count
if x > N or x < 0: return
if precalc[x] is None: return
if (a, k) not in precalc[x]:
precalc[x][(a, k)] = count
return
def factors(n):
res = []
for x in range(1, int(sqrt(n)) + 1):
if n % x == 0:
y = n / x
res.append((x, y))
res.append((y, x))
return res
def work(input):
precalc = [None] * (max(input) + 1)
for x in input: precalc[x] = {}
N = max(input)
res = ((0, 0), {"end":0, "count":0})
for i, x in enumerate(input):
for y in input[i::-1]:
for a, k in factors(x - y):
if (a, k) in precalc[x]: continue
add_precalc(precalc, x, (a, k), 2, res, N)
for step, count in precalc[x].iteritems():
count += 1
if count > res[1]["count"]: res = (step, {"end":x, "count":count})
add_precalc(precalc, x, step, count, res, N)
precalc[x] = None
d = [res[1]["end"]]
for x in range(res[1]["count"] - 1, 0, -1):
d.append(d[-1] - res[0][0] * res[0][1] ** x)
d.reverse()
return d
explanation
Traversing the array
For each previous element of the array calculate factors of the difference between current and taken previous element and then precalculate next possible element of the sequence and saving it to precalc array
So when arriving at element i there're already all possible sequences with element i in the precalc array, so we have to calculate next possible element and save it to precalc.
Currently there's one place in algorithm that could be slow - factorization of each previous number. I think it could be made faster with two optimizations:
more effective factorization algorithm
find a way not to see at each element of array, using the fact that array is sorted and there's already a precalculated sequences
Python:
def subseq(a):
seq = []
aset = set(a)
for i, x in enumerate(a):
# elements after x
for j, x2 in enumerate(a[i+1:]):
j += i + 1 # enumerate starts j at 0, we want a[j] = x2
bk = x2 - x # b*k (assuming k and k's exponent start at 1)
# given b*k, bruteforce values of k
for k in range(1, bk + 1):
items = [x, x2] # our subsequence so far
nextdist = bk * k # what x3 - x2 should look like
while items[-1] + nextdist in aset:
items.append(items[-1] + nextdist)
nextdist *= k
if len(items) > len(seq):
seq = items
return seq
Running time is O(dn^3), where d is the (average?) distance between two elements,
and n is of course len(a).

How many possible scorecards are consistent with the input scorecard?

I have been trying to solve the following problem in interview street. Count Scorecards(30 points)
In a tournament, N players play against each other exactly once. Each game results in either of the player winning. There are no ties. You have given a scorecard containing the scores of each player at the end of the tournament. The score of a player is the total number of games the player won in the tournament. However, the scores of some players might have been erased from the scorecard. How many possible scorecards are consistent with the input scorecard?
Input:
The first line contains the number of cases T. T cases follow. Each case contains the number N on the first line followed by N numbers on the second line. The ith number denotes s_i, the score of the ith player. If the score of the ith player has been erased, it is represented by -1.
Output:
Output T lines, containing the answer for each case. Output each result modulo 1000000007.
Constraints:
1 <= T <= 20
1 <= N <= 40
-1 <= s_i < N
Sample Input:
5
3
-1 -1 2
3
-1 -1 -1
4
0 1 2 3
2
1 1
4
-1 -1 -1 2
Sample Output:
2
7
1
0
12
Explanation:
For the first case, there are 2 scorecards possible: 0,1,2 or 1,0,2.
For the second case, the valid scorecards are 1,1,1, 0,1,2, 0,2,1, 1,0,2, 1,2,0, 2,0,1, 2,1,0.
For the third case, the only valid scorecard is {0,1,2,3}.
For the fourth case, there is no valid scorecard. It is not possible for both players to have score 1.
I have tried to come up with generic functions approach, but i am really trying to nail down this problem using Dynamic programming. How can you think of recurrence relations for this problem?.
Here is the DP solution to the above problem
public static int[][] table; // stores the result of the overlapping sub problems
private static int N;
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
int testCases = scanner.nextInt();
for (int i = 0; i < testCases; i++) {
N = scanner.nextInt();
int[] scores = new int[N];
for (int j = 0; j < N; j++) {
scores[j] = scanner.nextInt();
}
long result = process(scores) % 1000000007L;
System.out.println(result );
}
}
private static long process(int[] scores) {
int sum = 0;
int amongPlayers = 0; //count no of players whose score has been erased(-1)
for (int i = 0; i < N; i++) {
if (scores[i] != -1) {
sum += scores[i];
} else {
amongPlayers++;
}
}
int noGames = (N * (N -1)) /2; // total number of games
if (sum < noGames) {
int distribute = noGames - sum; // score needed to be distributed;
table = new int[distribute + 1 ][amongPlayers + 1];
for (int m = 0; m <= distribute; m++) {
for (int n = 0; n <= amongPlayers; n++) {
table[m][n] = -1;
}
}
return distribute(distribute, amongPlayers); // distrubute scores among players whose score is erased(-1)
}
else if(sum == noGames){
return 1;
}
return 0;
}
/**
* Dynamic programming recursive calls
* #param distribute
* #param amongPlayers
* #return
*/
private static int distribute(int distribute, int amongPlayers) {
if(distribute == 0 && amongPlayers == 0)
return 1;
if (amongPlayers <= 0)
return 0;
if(distribute == 0)
return 1;
int result = 0;
if (table[distribute][amongPlayers - 1] == -1) {
int zeroResult = distribute(distribute, amongPlayers - 1);
table[distribute][amongPlayers - 1] = zeroResult;
}
result += table[distribute][amongPlayers - 1];
for (int i = 1; i < N ; i++) { // A person could win maximum of N-1 games
if (distribute - i >= 0) {
if (table[distribute - i][amongPlayers - 1] == -1) {
int localResult = distribute(distribute - i,
amongPlayers - 1);
table[distribute - i][amongPlayers - 1] = localResult;
}
result += table[distribute - i][amongPlayers - 1];
}
}
return result;
}
Observations:
Sequence s[1], s[2], ..., s[n] to be consistent scorecard, these properties must hold:
s[i1] + s[i2] + .. + s[ik] >= k * (k — 1) / 2, where i1 < i2 < .. < ik (i.e for every subsequences of length k)
s[1] + s[2] + .. + s[n] = n * (n — 1) / 2
First of all we need to check not erased scores, just using 1 condition. Then put erased scores using dynamic programming.
Let's denote erased scores b[i], not erased scores a[i];
sum{i = 1 .. l} a[i] + sum{i = 1 .. k} b[i] >= (k + l) * (k + l - 1) / 2
sum{i = 1 .. l} a[i] + sum{i = 1 .. k} b[i] >= 0 + 1 + .. + (k + l - 1)
sum{i = 1 .. l} (a[i] - (k + i - 1)) + sum{i = 1 .. k} b[i] >= 0 + 1 + .. + (k - 1)
So we can pre calculate for every k, minimal value of sum{i = 1 .. l} (a[i] - (k + i - 1))/
Dynamic programming:
states:
dp[k][score][sum]: we know first k minimum erased scores, and their values not exceeds $score$, and sum is their sum.
transitions:
Skip score, dp[k][score][sum] += dp[k][score + 1][sum];
Put $i$ scores of value $score$ dp[k][score][sum] += C[m — k][i] * dp[k + i][score + 1][sum + i*score], where m number of erased scores, C[n][k] = combination.
my code
The total sum of the wins should be (N C 2)
Subtract the known values which are given in the input. Let the remaining sum (N C 2) - x be called S. Let the number of -1's in the input be Q.
The problem now boils down to finding the number of integral solutions of Q variables ranging from 0 to N-1 (max score possible) and sum of which is S
Let DP[q][s] denote the number of integral solutions of q variables whose sum is s
Then we have,
DP[q][s] = Sum (i=0 to N-1) DP[q-1][s-i]
DP[Q][S] gives the solution
EDIT:
Observation:
For x people remaining, the number of total wins should be at least x*(x-1)/2 (when they play each other). Thus, at any time for q people, s cannot exceed (N-q)(N-q-1)/2 = M
There should be one more constraint that DP[q][s] should be equal to 0 when s is greater than M
I'm trying to solve this assignment, too, and think it should be something like this:
The number of players (=N), the number of unknown cards (count the "-1") and the sum of the known cards (count all cards except "-1") are given. The total number of games possible should be 1 +2 +3 + ... + (players-1): The first player has (players-1) opponents, the second player (players-2) etc.
Now you can recursively calculate the sum of possible score cards:
Initialize an empty hashmap with (players, unknown cards, sum of known cards) as the key and the sum of possible score cards as the value.
If all cards are defined, then the answer is either 0 (if the sum of all cards equals the total number of games possible) or 1 (if the sum of all cards does not equal the total number of games possible).
If not all cards are defined, then run a for loop and set one unknown card to 0, 1, 2 ... (players-1) and try to read the result from the hashmap. If it is not in the hashmap call the method itself and save the result in the map.
The recursion code should be something like this:
def recursion(players: Int, games: Int, unknownCards: Int, knownScore: Int): Int = {
unknownCards match {
case 0 if knownScore != games => 0
case 0 if knownScore == games => 1
case _ =>
map.get(players, unknownCards, knownScore) getOrElse {
var sum = 0
for (i <- 0 until players) sum += main(players, games, unknownCards - 1, knownScore + i)
sum %= 1000000007
map.put((players, unknownCards, knownScore), sum)
sum
}
}
}
Try this
import java.util.Scanner;
public class Solution {
final private static int size = 780;
private static long[][] possibleSplits = new long[size][size];
static {
for(int i=0; i < size; ++i)
possibleSplits[i][0] = 1;
for(int j=0; j< size; ++j)
possibleSplits[0][j] = j+1;
for(int i=1; i< size; ++i)
for(int j=1; j < size; ++j)
{
possibleSplits[i][j] = (possibleSplits[i-1][j] + possibleSplits[i][j-1]) % 1000000007;
}
}
public long possibleWays = 0;
public Solution(int n, String scores)
{
long totalScores = 0;
int numOfErasedScores = 0;
for(String str : scores.split(" "))
{
int s = Integer.parseInt(str);
if (s < 0)
++numOfErasedScores;
else
totalScores += s;
}
long totalErasedScores = ncr(n,2) - totalScores;
if(totalErasedScores == 0)
++possibleWays;
else if (totalErasedScores > 0)
partition(n-1, totalErasedScores, numOfErasedScores);
}
private void partition(int possibleMax, long total, int split)
{
if (split == 0)
return;
possibleWays = possibleSplits[(int)total-1][split-1];
if (total > possibleMax)
possibleWays -= split;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int numberOfTestCases = Integer.parseInt(in.nextLine().trim());
for(int i=0; i< numberOfTestCases; ++i)
{
String str = in.nextLine().trim();
int numberOfPlayers = Integer.parseInt(str);
String playerScores = in.nextLine().trim();
long result = new Solution(numberOfPlayers, playerScores).possibleWays;
System.out.println(result % 1000000007);
}
in.close();
}
public static long ncr(int n, int r)
{
long result = 1;
for(int i= Math.max(n-r, r)+1;i<=n;++i)
result*= i;
result/= fact(Math.min(n-r,r));
return result;
}
public static long fact(int n)
{
long result = 1;
for(int i =2; i<= n; ++i)
result *= i;
return result;
}
}

Get next integer on base of individual digit

I need code or pointer for performing digit-wise addition. For example:
59 + 11 = 60
55 + 11 = 66
99 + 11 = 00
Basically, I want to ignore carry when 9 + 1. So 9 + 1 should return 0 and not 10, and for any other digit it should return actual sum (i.e 5 + 1 = 6).
If you want to increment the digits individually
f(x) = (x/10 + 1) % 10 * 10 + (x % 10 + 1) % 10
(Where % is the mod operator - it returns the remainder after division)
Use int digits = log10(x) to get the number of digits, then extract each digit x, replace with x + 1 % 10 and then put them back together, something like this:
int number = N; // STARTS AS THE ORIGINAL NUMBER
int answer = 0; // WILL BE THE NEXT NUMBER
int power = 1; // KEEPS TRACK OF POSITION
int digits = log10(x); // TOTAL NUMBER OF DIGITS
for (int d=0; d<digits; ++d) {
int x = (number + 1) % 10; // GET NEXT DIGIT, INCREMENT IT
answer += x*power; // ADD TO ANSWER IN CORRECT POSITION
number = (number-x)/10; // REMOVE DIGIT FROM NUMBER
power *= 10; // INCREMENT POSITION
}
To do this you need to extract the tens digit and ones digit seperately, add them seperately, then put them back together.
Here's an example: note that it isn't going to help you prevent the carries for the hundreds. For that you'd have to adapt the algorithm to handle it specifically, or split up the numbers by digits and add them that way.
int crazyAdd(int a, int b) {
int aTens = a % 10;
int bTens = b % 10;
int tens = aTens + bTens;
int ones = (a + b) % 10;
return tens + ones;
}
Here's one that's more flexible
int crazyAdd(int a, int b) {
int[] aDigits = extractDigits(a); // let there exist a function that
int[] bDigits = extractDigits(b); // puts the digits into an array
int size = aDigits.length;
if(size < bDigits.length) size = bDigits.length;
int digits = new int[size];
for(int i = 0; i < digits.length; i++) {
int aDigit = i >= aDigits.length ? 0 : aDigits[i];
int bDigit = i >= bDigits.length ? 0 : bDigits[i];
digits[i] = (aDigit + bDigit) % 10;
}
int result = 0;
for(int digit : digits) {
result = result * 10 + digit;
}
return result;
}
I'm pretty sure it would be a pain in the ass mathematically, so the easiest would be to iterate through digits and rotate them. In Ruby:
def rotate_digits(n)
result = 0
exp = 1
while n > 0
digit = n % 10
n /= 10
digit = (digit + 1) % 10
result += exp * digit
exp *= 10
end
result
end
puts rotate_digits(59)
puts rotate_digits(55)
puts rotate_digits(99)
This gives you a number, so the last one gives you 0. If you really want "00", it's easier to work with strings:
def rotate_digits_as_string(n)
n.to_s.each_char.map { |c| ((c.to_i + 1) % 10).to_s }.join
end
puts rotate_digits_as_string(59)
puts rotate_digits_as_string(55)
puts rotate_digits_as_string(99)
If you're only talking about two-digit numbers, you can use a rather simple form:
def nextNum (num):
val = int(num)
if num == "99":
return "00"
if val > 89:
return "0" + str(val - 89)
if val % 10 == 9:
return str (val + 1)
return str (val + 11)
Here's a little Python program showing that in action:
def nextNum (num):
if num == "99":
return "00"
val = int(num)
if val > 89:
return "0%d"%(val - 89)
if val % 10 == 9:
return "%02d"%(val + 1)
return "%02d"%(val + 11)
for i in range (0,100):
s = "%02d"%(i)
print "%s -> %s"%(s,nextNum(s))
We need to do this for each character in the string input.
We have a function which will do this one character at a time.
char inc(char ch)
{
ch = (ch + 1) % '0'; // ANSI.
return(ch);
}
Now we need a function that will do this to every character in the string:
string szinc(string input)
{
for(i = 0; i < input.size(); i = i + 1)
{
input[i] = inc(input[i]);
}
return(input);
}

Resources