Get a sequence number from 0 and alternate positive/negative incrementing every other time - math

I would like to be able to obtain a (non-convergent) sequence of numbers by a simple calculation that would look like this: 0, 1, -1, 2, -2, 3, -3, 4, -4 ...
By simple calculation I mean being able to do it with a single variable that would start from 1 (or 0) without having to rearrange this sequence.
I made several (unsuccessful) attempts in Lua, here is what it should look like in principle (this example only alternates 0s and 1s):
do
local n = 0
for i = 1, 10 do print(n)
n = n==0 and 1 or -n + (n/n)
end
end
Is this possible and how?
Update:
I just succeeded like this:
local n, j = 0, 2
for i = 1, 10 do print(n)
n = n==0 and 1 or j%2==0 and -(n+(n/math.abs(n))) or -n
j = j + 1
end
But I have to help myself with a second variable, I would have liked to know if with only n it would be possible to do it?

The whole numbers are enumerable. Thus there exists a mapping from the natural numbers to whole numbers. You'll now have to use a loop to loop over natural numbers, then compute a function that gives you a whole number:
-- 0, 1...10, -1...-10 -> 21 numbers total
for n = 1, 21 do
local last_bit = n % 2
local sign = 1 - (2 * last_bit)
local abs = (n - last_bit) / 2
print(sign * abs)
end
prints
-0
1
-1
2
-2
...
10
-10
on Lua 5.1; on newer Lua versions, you can use n // 2 instead of (n - last_bit) / 2 to (1) use ints and (2) make extracting the abs cheaper.

Simply "emit" both n and -n in each iteration:
for n = 0, 10 do
print(n)
print(-n)
end

My problem was solved by #EgorSkriptunoff in comment of my question, his approach is:
n = (n > 0 and 0 or 1) - n
The output of:
local n = 0
for i=1,10 do io.write(n..", ")
n = (n > 0 and 0 or 1) - n
end
Actually gives:
0, 1, -1, 2, -2, 3, -3, 4, -4, 5,

Related

Is there a function f(n) that returns the n:th combination in an ordered list of combinations without repetition?

Combinations without repetitions look like this, when the number of elements to choose from (n) is 5 and elements chosen (r) is 3:
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
As n and r grows the amount of combinations gets large pretty quickly. For (n,r) = (200,4) the number of combinations is 64684950.
It is easy to iterate the list with r nested for-loops, where the initial iterating value of each for loop is greater than the current iterating value of the for loop in which it is nested, as in this jsfiddle example:
https://dotnetfiddle.net/wHWK5o
What I would like is a function that calculates only one combination based on its index. Something like this:
tuple combination(i,n,r) {
return [combination with index i, when the number of elements to choose from is n and elements chosen is r]
Does anyone know if this is doable?
You would first need to impose some sort of ordering on the set of all combinations available for a given n and r, such that a linear index makes sense. I suggest we agree to keep our combinations in increasing order (or, at least, the indices of the individual elements), as in your example. How then can we go from a linear index to a combination?
Let us first build some intuition for the problem. Suppose we have n = 5 (e.g. the set {0, 1, 2, 3, 4}) and r = 3. How many unique combinations are there in this case? The answer is of course 5-choose-3, which evaluates to 10. Since we will sort our combinations in increasing order, consider for a minute how many combinations remain once we have exhausted all those starting with 0. This must be 4-choose-3, or 4 in total. In such a case, if we are looking for the combination at index 7 initially, this implies we must subtract 10 - 4 = 6 and search for the combination at index 1 in the set {1, 2, 3, 4}. This process continues until we find a new index that is smaller than this offset.
Once this process concludes, we know the first digit. Then we only need to determine the remaining r - 1 digits! The algorithm thus takes shape as follows (in Python, but this should not be too difficult to translate),
from math import factorial
def choose(n, k):
return factorial(n) // (factorial(k) * factorial(n - k))
def combination_at_idx(idx, elems, r):
if len(elems) == r:
# We are looking for r elements in a list of size r - thus, we need
# each element.
return elems
if len(elems) == 0 or len(elems) < r:
return []
combinations = choose(len(elems), r) # total number of combinations
remains = choose(len(elems) - 1, r) # combinations after selection
offset = combinations - remains
if idx >= offset: # combination does not start with first element
return combination_at_idx(idx - offset, elems[1:], r)
# We now know the first element of the combination, but *not* yet the next
# r - 1 elements. These need to be computed as well, again recursively.
return [elems[0]] + combination_at_idx(idx, elems[1:], r - 1)
Test-driving this with your initial input,
N = 5
R = 3
for idx in range(choose(N, R)):
print(idx, combination_at_idx(idx, list(range(N)), R))
I find,
0 [0, 1, 2]
1 [0, 1, 3]
2 [0, 1, 4]
3 [0, 2, 3]
4 [0, 2, 4]
5 [0, 3, 4]
6 [1, 2, 3]
7 [1, 2, 4]
8 [1, 3, 4]
9 [2, 3, 4]
Where the linear index is zero-based.
Start with the first element of the result. The value of that element depends on the number of combinations you can get with smaller elements. For each such smaller first element, the number of combinations with first element k is n − k − 1 choose r − 1, with potentially some of-by-one corrections. So you would sum over a bunch of binomial coefficients. Wolfram Alpha can help you compute such a sum, but the result still has a binomial coefficient in it. Solving for the largest k such that the sum doesn't exceed your given index i is a computation you can't do with something as simple as e.g. a square root. You need a loop to test possible values, e.g. like this:
def first_naive(i, n, r):
"""Find first element and index of first combination with that first element.
Returns a tuple of value and index.
Example: first_naive(8, 5, 3) returns (1, 6) because the combination with
index 8 is [1, 3, 4] so it starts with 1, and because the first combination
that starts with 1 is [1, 2, 3] which has index 6.
"""
s1 = 0
for k in range(n):
s2 = s1 + choose(n - k - 1, r - 1)
if i < s2:
return k, s1
s1 = s2
You can reduce the O(n) loop iterations to O(log n) steps using bisection, which is particularly relevant for large n. In that case I find it easier to think about numbering items from the end of your list. In the case of n = 5 and r = 3 you get choose(2, 2)=1 combinations starting with 2, choose(3,2)=3 combinations starting with 1 and choose(4,2)=6 combinations starting with 0. So in the general choose(n,r) binomial coefficient you increase the n with each step, and keep the r. Taking into account that sum(choose(k,r) for k in range(r,n+1)) can be simplified to choose(n+1,r+1), you can eventually come up with bisection conditions like the following:
def first_bisect(i, n, r):
nCr = choose(n, r)
k1 = r - 1
s1 = nCr
k2 = n
s2 = 0
while k2 - k1 > 1:
k3 = (k1 + k2) // 2
s3 = nCr - choose(k3, r)
if s3 <= i:
k2, s2 = k3, s3
else:
k1, s1 = k3, s3
return n - k2, s2
Once you know the first element to be k, you also know the index of the first combination with that same first element (also returned from my function above). You can use the difference between that first index and your actual index as input to a recursive call. The recursive call would be for r − 1 elements chosen from n − k − 1. And you'd add k + 1 to each element from the recursive call, since the top level returns values starting at 0 while the next element has to be greater than k in order to avoid duplication.
def combination(i, n, r):
"""Compute combination with a given index.
Equivalent to list(itertools.combinations(range(n), r))[i].
Each combination is represented as a tuple of ascending elements, and
combinations are ordered lexicograplically.
Args:
i: zero-based index of the combination
n: number of possible values, will be taken from range(n)
r: number of elements in result list
"""
if r == 0:
return []
k, ik = first_bisect(i, n, r)
return tuple([k] + [j + k + 1 for j in combination(i - ik, n - k - 1, r - 1)])
I've got a complete working example, including an implementation of choose, more detailed doc strings and tests for some basic assumptions.

How do I make 100 = 1? (explanation within)

Right now I have a code that can find the number of combinations of a sum of a value using numbers greater than zero and less than the value.
I need to alter the value in order to expand the combinations so that they include more than just the value.
For example:
The number 10 yields the results:
[1, 2, 3, 4], [1, 2, 7],
[1, 3, 6], [1, 4, 5],
[1, 9], [2, 3, 5], [2, 8],
[3, 7], [4, 6]
But I need to expand this to including any number that collapses to 1 as well. Because in essence, I need 100 = n in that the sum of the individual numbers within the digits = n. So in this case 100 = 1 because 100 --> 1+0+0 = 1
Therefore the number 1999 will also be a valid combination to list for value = 100 because 1999 = 1+9+9+9 = 28, and 28 = 2+8 = 10, and 10 = 1+0 = 1
Now I realize that this will yield an infinite series of combinations, so I will need to set limits to the range I want to acquire data for. This is the current code I am using to find my combinations.
def a(lst, target, with_replacement=False):
def _a(idx, l, r, t, w):
if t == sum(l): r.append(l)
elif t < sum(l): return
for u in range(idx, len(lst)):
_a(u if w else (u + 1), l + [lst[u]], r, t, w)
return r
return _a(0, [], [], target, with_replacement)
for val in range(100,101):
s = range(1, val)
solutions = a(s, val)
print(solutions)
print('Value:', val, "Combinations", len(solutions))
You seem to have multiple issues.
To repeatedly add the decimal digits of an integer until you end with a single digit, you could use this code.
d = val
while d > 9:
d = sum(int(c) for c in str(d))
This acts in just the way you describe. However, there is an easier way. Repeatedly adding the decimal digits of a number is called casting out nines and results in the digital root of the number. This almost equals the remainder of the number when divided by nine, except that you want to get a result of 9 rather than 1. So easier and faster code is
d = val % 9
if d == 0:
d == 9
or perhaps the shorter but trickier
d = (val - 1) % 9 + 1
or the even-more-tricky
d = val % 9 or 9
To find all numbers that end up at 7 (for example, or any digit from 1 to 9) you just want all numbers with the remainder 7 when divided by 9. So start at 7 and keep adding 9 and you get all such values.
The approach you are using to find all partitions of 7 then arranging them into numbers is much more complicated and slower than necessary.
To find all numbers that end up at 16 (for example, or any integer greater than 9) your current approach may be best. It is difficult otherwise to avoid the numbers that directly add to 7 or to 25 without going through 16. If this is really what you mean, say so in your question and we can look at this situation further.

Can this be expressed using Integer Programming or Constraint Programming?

Consider a fixed m by n matrix M, all of whose entries are 0 or 1. The question is whether there exists a non zero vector v, all of whose entries are -1, 0 or 1 for which Mv = 0. For example,
[0 1 1 1]
M_1 = [1 0 1 1]
[1 1 0 1]
In this example, there is no such vector v.
[1 0 0 0]
M_2 = [0 1 0 0]
[0 0 1 0]
In this example, the vector (0,0,0,1) gives M_2v = 0.
I am currently solving this problem by trying all different vectors v.
However, is it possible to express the problem as an integer
programming problem or constraint programming problem so I can use an
existing software package, such as SCIP instead which might be more
efficient.
It would help a little if you also give a positive example, not just a negative.
I might have missed something in the requirement/definitions, but here is a way of doing it in the Constraint Programming (CP) system MiniZinc (http://minizinc.org/). It don't use any specific constraints unique to CP systems - except perhaps for the function syntax, so it should be possible to translate it to other CP or IP systems.
% dimensions
int: rows = 3;
int: cols = 4;
% the matrix
array[1..rows, 1..cols] of int: M = array2d(1..rows,1..cols,
[0, 1, 1, 1,
1, 0, 1, 1,
1, 1, 0, 1,
] );
% function for matrix multiplication: res = matrix x vec
function array[int] of var int: matrix_mult(array[int,int] of var int: m,
array[int] of var int: v) =
let {
array[index_set_2of2(m)] of var int: res; % result
constraint
forall(i in index_set_1of2(m)) (
res[i] = sum(j in index_set_2of2(m)) (
m[i,j]*v[j]
)
)
;
} in res; % return value
solve satisfy;
constraint
% M x v = 0
matrix_mult(M, v) = [0 | j in 1..cols] /\
sum(i in 1..cols) (abs(v[i])) != 0 % non-zero vector
;
output
[
"v: ", show(v), "\n",
"M: ",
]
++
[
if j = 1 then "\n" else " " endif ++
show(M[i,j])
| i in 1..rows, j in 1..cols
];
By changing the definition of "M" to use decision variables with the domain 0..1 instead of constants:
array[1..rows, 1..cols] of var 0..1: M;
then this model yield 18066 different solutions, for example these two:
v: [-1, 1, 1, 1]
M:
1 0 0 1
1 1 0 0
1 0 0 1
----------
v: [-1, 1, 1, 1]
M:
0 0 0 0
1 0 1 0
1 0 0 1
Note: Generating all solutions is probably more common in CP systems than in traditional MIP systems (this is a feature that I really appreciate).

Combinations of integers adding up to a specific number

I need a program for all the combinations of the alphabet "01234", of length 5, of which the digits add up to 4 or less.
Examples
00013,
00031,
00101,
10120
but not
11213, 00341
Questions:
How to calculate the number of strings that add up to X ?
How to generate all strings that add up to X ?
How to generate all strings that add up to a number <=X ?
What is this concept called in mathematics ?
update:
How to find the subset(s) of digits (numbers) that add to sum X ?
Any procedural language or pseudo code will do. By concept I mean finding the subset(s) of numbers that will add up to a given sum. So, in addition I would like to get an algorithm to find these subsets. Finding all combinations and then filtering out the ones that match is easy, but not time efficient for larger alphabets (strings of digits).
Suppose you want all combinations(it seems more like permutations from your question, because you listed both 00013 and 00031) that sum up to 4, I think first you need a number partition program to partition the sum 4 into parts, and extend each partition's length into 5 by adding zeros, like this:
1, 1, 1, 1 -> 1, 1, 1, 1, 0
1, 1, 2 -> 1, 1, 2, 0, 0
1, 3 -> 1, 3, 0, 0, 0
2, 2 -> 2, 2, 0, 0, 0
4 -> 4, 0, 0, 0, 0
then you can do permutation on each of them. Because there are many duplicates in the number, the total number of permutations are not that big, for example, 1,1, 1, 1, 0 have only 5 permutations, 11110, 11101, 11011, 10111, 01111.
on how to do number partition, you can check out here, as for permutation, as I am a C++ programmer, I would use the next_permutation function in STL library, or check out here.
This method is pretty generic, you can deal with combinations of any sum without deep loop.
Here is a quick and dirty one. I am sure you will find ways to make it more effective. The code uses arrays instead of strings.
// Calculate sum of all digits
func numsum(a: [Int]) -> Int {
return reduce(a, 0, { $0 + $1 })
}
// Maximum number allowed
let maxnum = 4
// Number of digits
let arlen = 5
// Number we are looking for
let reqnum = 4
// Array that holds the combinations
var a = Array(count: arlen, repeatedValue: 0)
// Array where we keep all positive results
var b = [[Int]]()
// Function to go over all combinations and storing those that add up to the number we are looking for
// Called recursively for each level starting with 0
func addNum(level: Int = 0) {
if level == arlen {
return
}
a[level] = 0
while a[level] <= maxnum {
//println(a)
if numsum(a) == reqnum {
b.append(a)
}
else {
addNum(level: level + 1)
}
a[level] += 1
}
}
// Calling the function
addNum()
// Printing it out so that it looks like strings
for arr in b {
for n in arr {
print(n)
}
println()
}
Other Q&D solution, in Python
for a in range(5):
for b in range(5):
for c in range(5):
for d in range(5):
for e in range(5):
if a + b + c + d + e <= 4:
print a, b, c, d, e
You can replace the <= by ==, or the print by a N+= 1.
There are 70 "arrangements with repetition" giving sum 4, and126 with sum <= 4.
(Composition) is a good starting point. It gets complicated by allowing zeros (which requires considering orderings).
Though the zeros complicate it, and you'd probably have to ask on math stack to be able to get a general formula as combinatorics can get rather tricky. Otherwise, the other answers are sufficient your question.
I believe that recursive code is short and clear. It outputs combinations in lexicographic order, without redundant work.
procedure Combine(Digits, Sum, AMax: Integer; CurrentValue: string);
if Digits = 0 then
output(CurrentValue)
else
for i := 0 to Min(Sum, AMax) do
Combine(Digits - 1, Sum - i, AMax, CurrentValue + IntToStr(i));
//usage
Combine(4, 3, 3, '');
output:
0000
0001
0002
0003
0010
0011
0012
0020
0021
0030
0100
0101
0102
0110
0111
0120
0200
0201
0210
0300
1000
1001
1002
1010
1011
1020
1100
1101
1110
1200
2000
2001
2010
2100
3000

Testing divisibility of Ints by 11

I'm struggling with this code right now. I want to determine whether an integer is divsible by 11. From what I have read, an integer is divisible to 11 when the sum (one time +, one time -) of its digits is divisible by 11.
For example: 56518 is divisible by 11, because 8-1+5-6+5 = 11, and 11 is divisible by 11.
How can i write this down in Haskell? Thanks in advance.
A number x is divisible by y if it's remainder when divided by y is 0. So you can just do
divisibleBy11 x = x `rem` 11 == 0
ifan I'm sure you know that in real life you would use mod or rem for this simple example, but the algorithm you are asking about is interesting. Here's a fun way to do it that emphasizes the functional nature of Haskell:
digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)
divisible11 = (== 0) . head . dropWhile (>= 11) . iterate (reduce11 . digits)
where
reduce11 [] = 0
reduce11 (d:ds) = foldl combine d $ zip (cycle [(-), (+)]) ds
combine d (op, d') = d `op` d'
Surely, div and mod are faster, but why not? I assume the problem is converting a number to a list of digits:
toDigits = map (read . (:[])) . show
56518 is converted to a String "56518", and each symbol in the string (every digit) is converted to a string itself with map (:[]), at this point we have ["5","6","5","1","8"], and we read every single-digit string as an integer value: [5,6,5,1,8]. Done.
Now we can calculate the sum of digits this way:
sumDigits x = sum (zipWith (*) (cycle [1,-1]) (reverse (toDigits x)))
cycle [1,-1] makes an infinite list [1, -1, 1, -1, ...], which we pair with the reversed list of digits (toDigit x), and multiply elements of every pair. So we have [8, -1, 5, -6, 5] and its sum.
Now we can do it recursively:
isDivisible x
| x == 11 || x == 0 = True
| x < 11 = False
| x > 11 = isDivisible (sumDigits x)
How about...
mod11 n | n < 0 = 11 - mod11 (-n)
| n < 11 = n
| otherwise = mod11 $ (n `mod` 10) - (n `div` 10)

Resources