Generate and check the primality of very large numbers in Livecode - random

How can I do this? All other results on these yield languages that aren't LiveCode or do not work in LiveCode for some reason. The numbers have to be randomly generated; otherwise, I could just take a few from here (yes, ~150 digits). The end goal is to use these for encryption (a personal experiment).

You do not say what you have done so far. The basic method for generating a large prime is:
repeat
pick a large possible prime
until (the number you picked is prime)
That is pseudocode since I do not know LiveCode. You will have to do the conversion yourself.
All large primes are of the form 6n ± 1. You can choose n in a suitable range for the size of prime you want.
For the prime testing you are going to have to convert one of the standard primality tests to LiveCode. Alternatively, is there a way to incorporate an external method in some other language into LiveCode, which would let you copy an example from the web?

How large are we talking here? Most programming languages use standard numeric types to store numbers internally, that are of a fixed size (e.g. 4 bytes give you numbers from about -2 billion through +2 billion).
So they're unlikely to be able to deal with numbers as large as 150 digits.
You may have to get a LiveCode plugin (external? Whatever LiveCode used to call them) that can deal with very big numbers or performs "string maths".

Mr Devin Asay of the LiveCode use-list offers this:
on mouseUp
local tNum
put fld 2 into tNum
put "" into fld 1
put isPrime(tNum) into fld 1
end mouseUp
function isPrime pNum
if pNum <> 2 AND pNum mod 2 = 0 then
return false
end if
repeat with x = 3 to sqrt(pNum) step 2
if pNum mod x = 0 then
return false
end if
end repeat
return true
end isPrime
The handler fails at 309 digits, due to a range (overflow) error. This is a machine limitation, not a LC one. The precision of the handler overall is limited (per Mark Waddingham of the LC team):
You can only represent integers up to around 2^53 without losing
precision (as they are represented using IEEE doubles) which means the
maximum number you can check for primality using this method is around
9007199254740992.

I have no problem to deal with total perfection with number long any digits you wisk using livecode or any other language. I can work with just the + - / * operation, but I think that's is enough for your research. I made this functions:
function bigAdd a1, a2
#let's check if it's negative...
#end check
put reverse2(a1) into b1
put reverse2(a2) into b2
put 0 into mem
if length(b1) < length(b2) then
put b1 into temp
put b2 into b1
put temp into b1
end if
repeat while b2 is not empty
put (char 1 of b1) + (char 1 of b2) + mem into ppp
if length(ppp) = 1 then
put 0 into mem
put ppp before rrr
else
put 1 into mem
put char 2 of ppp before rrr
end if
delete char 1 of b1
delete char 1 of b2
end repeat
repeat while (b1 is not empty)
put mem + (char 1 of b1) into ppp
if length(ppp) = 1 then
put 0 into mem
put ppp before rrr
else
put 1 into mem
put char 2 of ppp before rrr
end if
delete char 1 of b1
end repeat
if mem = 1 then
put 1 before rrr
else
put b1 before rrr
end if
return rrr
end bigAdd
function reverse2 temp
repeat for each char tChar in temp
put tChar before temp2
end repeat
return temp2
end reverse2
function bigMultiply a1,a2
put reverse2(a1) into a1
put 0 into temp
repeat for each char tChar in a1
repeat with i=1 to tChar
put bigAdd(temp,a2) into temp
end repeat
put 0 after a2
end repeat
return temp
end bigMultiply
function bigGreater a1,a2
#compare two bignumbers:
#return true if n1 > n2
#return false if n1 < n2
#return empty if n1 = n2
#let's check is a number is negative
if ((char 1 of a1 = "-") or (char 1 of a2 = "-")) then
if ((char 1 of a1 = "-") and (char 1 of a2 is not "-")) then
return false
end if
if ((char 1 of a1 is not "-") and ( char 1 of a2 = "-" )) then
return true
end if
#if we are here, both are negative
delete char 1 of a1
delete char 1 of a2
if a1 = a2 then
return empty
else
return (not bigGreater(a1,a2))
end if
end if
if length(a1) is not length(a2) then
return ( length(a1) > length(a2) ) #this is evalueted true or false
else
if a1 = a2 then
return empty
else
repeat while ((char 1 of a1) = (char 1 of a2) )
delete char 1 of a1
delete char 1 of a2
end repeat
return ((char 1 of a1) > (char 1 of a2)) #this is evalueted true or false
end if
end if
end bigGreater
function bigSub a1,a2
#substract the smallest big number from the largest one
if bigGreater(a2,a1) then
put a1 into temp
put a2 into a1
put temp into a2
end if
put reverse2(a1) into a1
put reverse2(a2) into a2
put 0 into mem
repeat while (a2 is not empty)
put (char 1 of a1) - mem + 10 - (char 1 of a2) into minus
if length(minus) = 1 then
put 1 into mem
put minus before rrr
else
put 0 into mem
put char 2 of minus before rrr
end if
delete char 1 of a1
delete char 1 of a2
end repeat
repeat while (a1 is not empty)
put char 1 of a1 + 10 - mem into minus
if length(minus) = 1 then
put 1 into mem
put minus before rrr
else
put 0 into mem
put char 2 of minus before rrr
end if
delete char 1 of a1
end repeat
#remove inital zeros
repeat while (char 1 of rrr is "0")
delete char 1 of rrr
end repeat
return rrr
end bigSub
function bigDivide a1,a2
#output is a block of two numbers "quotient , remainder"
if bigGreater(a2,a1) then
return ("0," & a1)
end if
if a1 = a2 then
return "1,0"
end if
put 0 into count
repeat while (bigGreater(a1,a2))
put bigSub(a1,a2) into a1
put bigAdd(1,count) into count
end repeat
if a1 = a2 then
put bigAdd(count,1) into count
put 0 into a1
end if
return (count & comma & a1)
end bigDivide
function bigDivide2 a1,a2
#please note that the result is "the result, the remainder"
put length(a1) into ldividendo
put length(a2) into ldivisore
if ldividendo <= ldivisore then
return bigDivide(a1,a2)
end if
put char 1 to ldivisore of a1 into tDiv
put bigDivide(tDiv,a2) into rrr
put item 1 of rrr into quoziente
put item 2 of rrr into resto
put ldivisore + 1 into nn
repeat with i = nn to ldividendo
put char i of a1 after resto
put bigDivide(resto,a2) into temp
put item 1 of temp after quoziente
put item 2 of temp into resto
end repeat
put removezeros(quoziente) into quoziente
put removezeros(resto) into resto
return (quoziente & comma & resto)
end bigDivide2
function removezeros temp
repeat while char 1 of temp is "0"
delete char 1 of temp
end repeat
return temp
end removezeros

Related

Converting Number to Binary String

The following is the code to convert a number to binary string. Can anyone tell me how ans.push_back((char)('0' + rem)) works?
class Solution {
public:
string findDigitsInBinary(int n) {
string ans;
if (n == 0) return "0";
while (n > 0) {
int rem = n % 2;
ans.push_back((char)('0' + rem));
n /= 2;
}
reverse(ans.begin(), ans.end());
return ans;
}
};
To understand it, you just need to know that you can do arithmetic operations on char variables too. So, the simple loop below is valid and will print 0123456789.
for(char c = '0'; c <= '9'; ++c)
cout << c;
In you code, rem is either 0 or 1. So, (char)('0'+rem) is either '0' or '1' as desired, corresponding to rem=0, 1, respectively.
while (n > 0) {
int rem = n % 2;
ans.push_back((char)('0' + rem));
n /= 2;
}
Focus on this loop. Suppose n is 5
n > 0 true so enter into loop. rem = n % 2 so rem = 5 % 2 = 1
ans.push_back((char)('0' + rem)) here ('0' + rem) is (48 + 1) ASCII of '0' is 48
Now convert 48 + 1 = 49 into char that is '1'. Now push '1' into ansand then n /= 2 is 5 /= 2 that is 2. Now go back and check the condition in while loop. After loop reverse the content of ans and you have binary string of number n
First you get rem as %2. Thus the value of rem can either be 0 or 1.
In ans.push_back((char)('0' + rem)); you need to add the corresponding character to the string, that is either 0 or 1. For this you have considered '0' as base character and you simply add the rem to it, using its ASCII int. When doing such integer operation, the ASCII value of character '0' is considered, which is 48. Thus after adding rem to it, it can either be 48 + 0 = 48 or 48 + 1 = 49.
Finally, this value is type casted back to char, with 48 being '0' and 49 being '1'

VBA permutations of undetermined number of variables

Recently I am trying to get the permutation of undetermined number of variables. For undetermined I mean I was aiming to create an input box for users to put in the number.
Start from simple. Originally I was aiming to get a 4 digits permutations with each digit have different number of variables, i.e. 1st digit can only be A,B,C,D; 2nd digit be E,F; 3rd digit be G, H etc. Code are below:
Sub Permut()
Count = 1
For a = 1 To 4
For b = 1 To 2
For c = 1 To 2
For d = 1 To 2
For e = 1 To 2
'chr(97) is the alphabet "a"
Cells(Count, 1) = Chr(96 + a) & Chr(96 + Len(a) + b) & Chr(96 + Len(a) + Len(b) + c) & _
Chr(96 + Len(a) + Len(b) + Len(c) + d) & Chr(96 + Len(a) + Len(b) + Len(c) + Len(d) + e)
Count = Count + 1
Next
Next
Next
Next
Next
End Sub
This will give you 64 different combinations without repetition.
Just wondering is there a way to generalize this process so that people can choose how many variables in total as well as within each digit?
Thank you.
Here is a solution, where you would pass the Permut function the minimum value for each of the characters (digits) as one string, and the maximum characters also as a string. Both strings should have an equal number of characters of course:
Function Permut(min, max)
Dim str, nxt, count
str = min
count = 1
Do While str < max
Cells(count, 1) = str
count = count + 1
nxt = ""
For i = Len(str) To 1 Step -1
If Mid(str, i, 1) < Mid(max, i, 1) Then
nxt = ChrW(AscW(Mid(str, i, 1))+1) & nxt
Exit For
End If
nxt = Mid(min, i, 1) & nxt
Next
str = Left(str, Len(str) - Len(nxt)) & nxt
Loop
Cells(count, 1) = str
End Sub
You would call it like this:
Permut "abc", "bcf"
That example would produce this list on your sheet:
abc
abd
abe
abf
acc
acd
ace
acf
bbc
bbd
bbe
bbf
bcc
bcd
bce
bcf
How to Execute This with User Input and Button Click
If you want to call this code in response to an event, such as a button click, and want to pass it the contents of two cells where the user would first enter the min and max strings, then follow these steps:
Place an ActiveX command button on your sheet (put it somewhere in D1 to leave room for some other stuff)
Double click it to generate the empty click event handler. If that does not work, go to the code window and select the name of the button from the drop-down at the top of the window, and select Click from the next drop down.
Complete the code of that event handler as follows (I assume the button is called CommandButton1, but don't change the generated name):
Code:
Private Sub CommandButton1_Click()
Permut Range("B1"), Range("C1")
End Sub
This code assumes the user has to enter the min and max digits/characters in cells B1 and C1. The A column is of course reserved for the output of the code.
For a more complete explanation on how to add a command button and attach code to its click event, read "Add a command button (ActiveX control)" in the Office manual.
credit to the answer from trincot above.
I have tried to run the code with a bit modification coz I am not sure how to get set value into cells (0,1). It keeps saying error. But If I change the starting point to Cells(1,1) then I will miss the last permutation. So I just add an additional if statement to get the code work as I want.
Function Permut(min, max)
Dim str, nxt, count
str = min
count = 1
Do While str < max
Cells(count, 1) = str
count = count + 1
nxt = ""
For i = Len(str) To 1 Step -1
If Mid(str, i, 1) < Mid(max, i, 1) Then
'asc("a")=97; chr(97) ="a"
nxt = Chr(AscW(Mid(str, i, 1)) + 1) & nxt
Exit For
End If
nxt = Mid(min, i, 1) & nxt
Next
str = Left(str, Len(str) - Len(nxt)) & nxt
If str = max Then
Cells(count, 1) = str
End If
Loop
End Function

scanning binary sequences of length n with k 1's and n-k 0's

I want to write a loop that scans all binary sequences of length n with k 1's and n-k 0's.
Actually, in each iteration an action is performed on the sequence and if a criterion is met the loop will break, otherwise it goes to next sequence. (I am not looking for nchoosek or perms since for large values of n it takes so much time to give the output).
What MATLAB code do you suggest?
You could implement something like an iterator/generator pattern:
classdef Iterator < handle
properties (SetAccess = private)
n % sequence length
counter % keeps track of current iteration
end
methods
function obj = Iterator(n)
% constructor
obj.n = n;
obj.counter = 0;
end
function seq = next(obj)
% get next bit sequence
if (obj.counter > 2^(obj.n) - 1)
error('Iterator:StopIteration', 'Stop iteration')
end
seq = dec2bin(obj.counter, obj.n) - '0';
obj.counter = obj.counter + 1;
end
function tf = hasNext(obj)
% check if sequence still not ended
tf = (obj.counter <= 2^(obj.n) - 1);
end
function reset(obj)
% reset the iterator
obj.counter = 0;
end
end
end
Now you can use it as:
k = 2;
iter = Iterator(4);
while iter.hasNext()
seq = iter.next();
if sum(seq)~=k, continue, end
disp(seq)
end
In the example above, this will iterate through all 0/1 sequences of length 4 with exactly k=2 ones:
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 0
1 1 0 0

Generating a repeatable pseudo-random number based coordinates

I need to generate repeatable pseudo random numbers based on a set of coordinates, so that with a given seed, I will always generate the same value for a specific coordinate.
I figured I'd use something like this for the seed:
/* 64bit seed value*/
struct seed_cord {
uint16 seed;
uint16 coord_x_int;
uint16 coord_y_int;
uint8 coord_x_frac;
uint8 coord_y_frac;
}
Where coord_x_int is the integer part of the coordinate, and the fraction part is given by coord_x_frac / 0xFF. seed is a randomly pre-determined value.
But I must admit, trying to understand all the intricacies of PRNGs is a little overwhelming. What would be a good generator for what I'm attempting?
I tested out Java's PRNG using using this scheme in a quick groovy script, with the following result:
Obviously, this is hardly decent randomness.
The script I used was:
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
short shortSeed = new Random().next(16) as short
def image = new BufferedImage(512, 512, BufferedImage.TYPE_BYTE_GRAY)
def raster = image.getRaster()
//x
(0..1).each{ x ->
(0..255).each{ xFrac ->
//y
(0..1).each{ y ->
(0..255).each{ yFrac ->
long seed = (shortSeed as long) << 48 |
(x as long) << 32 |
(y as long) << 16 |
(xFrac as long) << 8 |
(yFrac as long)
def value = new Random(seed).next(8)
raster.setSample( (x? xFrac+256 : xFrac), (y? yFrac+256 : yFrac), 0 , value)
}}}}
ImageIO.write(image, "PNG", new File("randomCoord.png"))
If you're really only looking at 512x512, then that's uh... 218 pixels you're interested in.
There's plenty of space for that kind of population with good ole MD5 (128 bit output).
You can just take the lowest 32 bits for an integer if that's the kind of output you need. Really, any sort of hashing algorithm that has an output space at least as large as an int will do.
Now, you can do all sorts of fun stuff if you're paranoid. Start with a hash of your coordinates, then feed the result into a secure random number generator (java.security.SecureRandom). Then hash it 1000 times with a salt that's your birthday concatenated (x+y) times.
Joking aside, random number generators don't necessarily have wildly varying results based on small variations of the seed. They're designed to have a really, super duper long chain of generated numbers before they start repeating, while having those chains pretty evenly distributed among the number space.
On the other hand, the SecureRandom is designed to have the additional feature of being chaotic in regard to the seed.
Most languages have a PRNG package (or two) that lets you initialize the generator with a specific seed. PRNGs can also often be found as part of a larger cryptographic package; they tend to be a bit stronger than those found in general-purpose libraries.
I would take a program like this one I have created and then modify it to pick coordinates:
REM $DYNAMIC
COMMON SHARED n%, rbuf%, sz%, sw%, p1$
DECLARE SUB initialize ()
DECLARE SUB filbuf ()
DECLARE SUB setup ()
DECLARE FUNCTION Drnd# ()
DECLARE SUB core ()
DECLARE SUB modify ()
DIM SHARED pad1(340) AS STRING * 1
DIM SHARED trnsltr(66) AS STRING * 1 ' translates a 0-67 value into a pad character
DIM SHARED trnslt(255) AS INTEGER 'translates a pad value to 0-67 value -1 if error
DIM SHARED moders(26) AS INTEGER 'modding function prim number array
DIM SHARED moders2(26) AS INTEGER 'modding function prim number array
DIM SHARED ranbuf(1 TO 42) AS DOUBLE 'random number buffer if this is full and rbuf %>0
REM then this buffer is used to get new random values
REM rbuf% holds the index of the next random number to be used
REM subroutine setup loads the prime number table
REM from the data statements to be used
REM as modifiers in two different ways (or more)
REM subroutine initialize primes the pad array with initial values
REM transfering the values from a string into an array then
REM makes the first initial scrambling of this array
REM initializing pad user input phase:
CLS
INPUT "full name of file to be encrypted"; nam1$
INPUT "full name of output file"; nam2$
INPUT "enter password"; p2$
rbuf% = 0
n% = 0: sw% = 0
p3$ = STRING$(341, "Y")
p1$ = "Tfwd+-$wiHEbeMN<wjUHEgwBEGwyIEGWYrg3uehrnnqbwurt+>Hdgefrywre"
p1$ = p2$ + p1$ + p3$
PRINT "hit any key to continue any time after a display and after the graphic display"
p1$ = LEFT$(p1$, 341)
sz% = LEN(p1$)
CALL setup
CALL initialize
CLS
ibfr$ = STRING$(512, 32)
postn& = 1
OPEN nam1$ FOR BINARY AS #1
OPEN nam2$ FOR BINARY AS #2
g& = LOF(1)
max& = g&
sbtrct% = 512
WHILE g& > 0
LOCATE 1, 1
PRINT INT(1000 * ((max& - g&) / max&)) / 10; "% done";
IF g& < 512 THEN
ibfr$ = STRING$(g&, 32)
sbtrct% = g&
END IF
GET #1, postn&, ibfr$
FOR ste% = 1 TO LEN(ibfr$)
geh% = INT(Drnd# * 256)
MID$(ibfr$, ste%, 1) = CHR$(geh% XOR ASC(MID$(ibfr$, ste%, 1)))
NEXT ste%
PUT #2, postn&, ibfr$
postn& = postn& + sbtrct%
g& = g& - sbtrct%
WEND
CLOSE #2
CLOSE #1
PRINT "hit any key to exit"
i$ = ""
WHILE i$ = "": i$ = INKEY$: WEND
SYSTEM
END
DATA 3,5,7,9,11,13,17,19
DATA 23,29,33,37,43,47
DATA 53,59,67,71,73,79,83
DATA 89,91,97,101,107,109
DATA 43,45,60,62,36
REM $STATIC
SUB core
REM shuffling algorythinm
FOR a% = 0 TO 339
m% = (a% + 340) MOD 341: bez% = trnslt(ASC(pad1(340)))
IF n% MOD 3 = 0 THEN pad1(340) = trnsltr((2 * trnslt(ASC(pad1(a%))) + 67 - trnslt(ASC(pad1(m%)))) MOD 67)
IF n% MOD 3 = 1 THEN pad1(340) = trnsltr((2 * (67 - trnslt(ASC(pad1(a%)))) + 67 - trnslt(ASC(pad1(m%)))) MOD 67)
IF n% MOD 3 = 2 THEN pad1(340) = trnsltr(((2 * trnslt(ASC(pad1(a%))) + 67 - trnslt(ASC(pad1(m%)))) + moders(n% MOD 27)) MOD 67)
pad1(a% + 1) = pad1(m%): n% = (n% + 1) MOD 32767
pad1(a%) = trnsltr((bez% + trnslt(ASC(pad1(m%)))) MOD 67)
NEXT a%
sw% = (sw% + 1) MOD 32767
END SUB
FUNCTION Drnd#
IF rbuf% = 0 THEN
CALL core
CALL filbuf
IF sw% = 32767 THEN CALL modify
END IF
IF rbuf% > 0 THEN yut# = ranbuf(rbuf%)
rbuf% = rbuf% - 1
Drnd# = yut#
END FUNCTION
SUB filbuf
q% = 42: temp# = 0
WHILE q% > 0
FOR p% = 1 TO 42
k% = (p% - 1) * 8
FOR e% = k% TO k% + 7
temp# = temp# * 67: hug# = ABS(trnslt(ASC(pad1(e%)))): temp# = temp# + hug#
NEXT e%
IF temp# / (67 ^ 8) >= 0 AND q% < 43 THEN
ranbuf(q%) = temp# / (67 ^ 8): q% = q% - 1
END IF
temp# = 0
NEXT p%
WEND
rbuf% = 42
END SUB
SUB initialize
FOR a% = 0 TO 340
pad1(a%) = MID$(p1$, a% + 1, 1)
NEXT a%
FOR a% = 0 TO 340
LOCATE 1, 1
IF a% MOD 26 = 0 THEN PRINT INT((340 - a%) / 26)
sum% = 0
FOR b% = 0 TO 340
qn% = INT(Drnd# * 81)
op% = INT(qn% / 3)
qn% = qn% MOD 3
IF qn% = 0 THEN sum% = sum% + trnslt(ASC(pad1(b%)))
IF qn% = 1 THEN sum% = sum% + (67 + 66 - trnslt(ASC(pad1(b%)))) MOD 67
IF qn% = 2 THEN sum% = sum% + trnslt(ASC(pad1(b%))) + moders(op%)
NEXT b%
pad1(a%) = trnsltr(sum% MOD 67)
NEXT a%
n% = n% + 1
END SUB
SUB modify
REM modifier shuffling routine
q% = 26
temp# = 0
WHILE q% > -1
FOR p% = 1 TO 27
k% = (p% - 1) * 4 + 3
FOR e% = k% TO k% + 3
temp# = temp# * 67
hug# = ABS(trnslt(ASC(pad1(e%))))
temp# = temp# + hug#
NEXT e%
IF (temp# / (67 ^ 4)) >= 0 AND q% > -1 THEN
SWAP moders(q%), moders(INT(27 * (temp# / (67 ^ 4))))
q% = q% - 1
END IF
temp# = 0
NEXT p%
WEND
END SUB
SUB setup
FOR a% = 0 TO 26
READ moders(a%)
moders2(a%) = moders(a%)
NEXT a%
REM setting up tables and modder functions
FOR a% = 0 TO 25
trnsltr(a%) = CHR$(a% + 97)
trnsltr(a% + 26) = CHR$(a% + 65)
NEXT a%
FOR a% = 52 TO 61
trnsltr(a%) = CHR$(a% - 4)
NEXT a%
FOR a% = 62 TO 66
READ b%
trnsltr(a%) = CHR$(b%)
NEXT a%
FOR a% = 0 TO 255
trnslt(a%) = -1
NEXT a%
FOR a% = 0 TO 66
trnslt(ASC(trnsltr(a%))) = a%
NEXT a%
RESTORE
END SUB
the call to drand# gives you random numbers from 0 to 1 simply multiply that by your needed range for each vector needed p2$ is the password that is passed to the password handler which combines it with some other random characters and then caps the size to a certain limit p1$ is where the final modified password is contained
drand# itself calls another sub which is actually a clone of itself with some shuffling of
sorts that works to ensure that the numbers being produced are truly random there is also a table of values that are added in to the values being added all this in total makes the RNG many many more times random with than without.
this RNG has a very high sensitivity to slight differences in password initially set you must however make an intial call to setup and initialize to "bootstrap" the random number generator this RNG will produce Truly random numbers that will pass all tests of randomness
more random even then shuffling a deck of cards by hand , more random than rolling a dice..
hope this helps using the same password will result in the same sequnece of vectors
This program would have to be modified a bit though to pick random vectors rather than
it's current use as a secure encryption random number generator...
You can use encryption for this task, for example AES. Use your seed as the password, struct with coordinates as the data block and encrypt it. The encrypted block will be your random number (you can actually use any part of it). This approach is used in the Fortuna PRNG. The same approach can be used for disk encryption where random access of data is needed (see Random access encryption with AES In Counter mode using Fortuna PRNG:)

How can I generate this pattern of numbers?

Given inputs 1-32 how can I generate the below output?
in. out
1
1
1
1
2
2
2
2
1
1
1
1
2
2
2
2
...
Edit Not Homework.. just lack of sleep.
I am working in C#, but I was looking for a language agnostic algorithm.
Edit 2 To provide a bit more background... I have an array of 32 items that represents a two dimensional checkerboard. I needed the last part of this algorithm to convert between the vector and the graph, where the index aligns on the black squares on the checkerboard.
Final Code:
--Index;
int row = Index >> 2;
int col = 2 * Index - (((Index & 0x04) >> 2 == 1) ? 2 : 1);
Assuming that you can use bitwise operators you can check what the numbers with same output have in common, in this case I preferred using input 0-31 because it's simpler (you can just subtract 1 to actual values)
What you have?
0x0000 -> 1
0x0001 -> 1
0x0010 -> 1
0x0011 -> 1
0x0100 -> 2
0x0101 -> 2
0x0110 -> 2
0x0111 -> 2
0x1000 -> 1
0x1001 -> 1
0x1010 -> 1
0x1011 -> 1
0x1100 -> 2
...
It's quite easy if you notice that third bit is always 0 when output should be 1 and viceversa it's always 1 when output should be 2
so:
char codify(char input)
{
return ((((input-1)&0x04)>>2 == 1)?(2):(1));
}
EDIT
As suggested by comment it should work also with
char codify(char input)
{
return ((input-1 & 0x04)?(2):(1));
}
because in some languages (like C) 0 will evaluate to false and any other value to true. I'm not sure if it works in C# too because I've never programmed in that language. Of course this is not a language-agnostic answer but it's more C-elegant!
in C:
char output = "11112222"[input-1 & 7];
or
char output = (input-1 >> 2 & 1) + '1';
or after an idea of FogleBird:
char output = input - 1 & 4 ? '2' : '1';
or after an idea of Steve Jessop:
char output = '2' - (0x1e1e1e1e >> input & 1);
or
char output = "12"[input-1>>2&1];
C operator precedence is evil. Do use my code as bad examples :-)
You could use a combination of integer division and modulo 2 (even-odd): There are blocks of four, and the 1st, 3rd, 5th block and so on should result in 1, the 2nd, 4th, 6th and so on in 2.
s := ((n-1) div 4) mod 2;
return s + 1;
div is supposed to be integer division.
EDIT: Turned first mod into a div, of course
Just for laughs, here's a technique that maps inputs 1..32 to two possible outputs, in any arbitrary way known at compile time:
// binary 1111 0000 1111 0000 1111 0000 1111 0000
const uint32_t lu_table = 0xF0F0F0F0;
// select 1 bit out of the table
if (((1 << (input-1)) & lu_table) == 0) {
return 1;
} else {
return 2;
}
By changing the constant, you can handle whatever pattern of outputs you want. Obviously in your case there's a pattern which means it can probably be done faster (since no shift is needed), but everyone else already did that. Also, it's more common for a lookup table to be an array, but that's not necessary here.
The accepted answer return ((((input-1)&0x04)>>2 == 1)?(2):(1)); uses a branch while I would have just written:
return 1 + ((input-1) & 0x04 ) >> 2;
Python
def f(x):
return int((x - 1) % 8 > 3) + 1
Or:
def f(x):
return 2 if (x - 1) & 4 else 1
Or:
def f(x):
return (((x - 1) & 4) >> 2) + 1
In Perl:
#!/usr/bin/perl
use strict; use warnings;
sub it {
return sub {
my ($n) = #_;
return 1 if 4 > ($n - 1) % 8;
return 2;
}
}
my $it = it();
for my $x (1 .. 32) {
printf "%2d:%d\n", $x, $it->($x);
}
Or:
sub it {
return sub {
my ($n) = #_;
use integer;
return 1 + ( (($n - 1) / 4) % 2 );
}
}
In Haskell:
vec2graph :: Int -> Char
vec2graph n = (cycle "11112222") !! (n-1)
Thats pretty straightforward:
if (input == "1") {Console.WriteLine(1)};
if (input == "2") {Console.WriteLine(1)};
if (input == "3") {Console.WriteLine(1)};
if (input == "4") {Console.WriteLine(1)};
if (input == "5") {Console.WriteLine(2)};
if (input == "6") {Console.WriteLine(2)};
if (input == "7") {Console.WriteLine(2)};
if (input == "8") {Console.WriteLine(2)};
etc...
HTH
It depends of the language you are using.
In VB.NET, you could do something like this :
for i as integer = 1 to 32
dim intAnswer as integer = 1 + (Math.Floor((i-1) / 4) mod 2)
' Do whatever you need to do with it
next
It might sound complicated, but it's only because I put it into a sigle line.
In Groovy:
def codify = { i ->
return (((((i-1)/4).intValue()) %2 ) + 1)
}
Then:
def list = 1..16
list.each {
println "${it}: ${codify(it)}"
}
char codify(char input)
{
return (((input-1) & 0x04)>>2) + 1;
}
Using Python:
output = 1
for i in range(1, 32+1):
print "%d. %d" % (i, output)
if i % 4 == 0:
output = output == 1 and 2 or 1
JavaScript
My first thought was
output = ((input - 1 & 4) >> 2) + 1;
but drhirsch's code works fine in JavaScript:
output = input - 1 & 4 ? 2 : 1;
and the ridiculous (related to FogleBird's answer):
output = -~((input - 1) % 8 > 3);
Java, using modulo operation ('%') to give the cyclic behaviour (0,1,2...7) and then a ternary if to 'round' to 1(?) or 2(:) depending on returned value.
...
public static void main(String[] args) {
for (int i=1;i<=32;i++) {
System.out.println(i+"="+ (i%8<4?1:2) );
}
Produces:
1=1 2=1 3=1 4=2 5=2 6=2 7=2 8=1 9=1
10=1 11=1 12=2 13=2 14=2 15=2 16=1
17=1 18=1 19=1 20=2 21=2 22=2 23=2
24=1 25=1 26=1 27=1 28=2 29=2 30=2
31=2 32=1

Resources