Z3Py solver from brute force script - reverse-engineering

I am working on a reverse-engineering challenge, the program takes a 32 bits hex number as input and do a serie of equations using a keyword, if the final result is 0 then the input is valid otherwise the input is wrong.
I wrote a python brute force script that tries every value from 0x11111111 to 0xffffffff :
username = "skander"
i = 286331153
while i < 4294967295 :
hash = i
print("Testing : %s") % (hex(hash))
for c in username :
hash = hash >> 27 | (hash ^ ord(c)) << 5
hash = hash & 0xffffffff
hash = hash ^ (hash << 8)
hash = hash & 0xffffffff
if hash == 0 :
print("****** FOUND ******")
print(hex(i))
break
else :
i = i + 1
After some attempts, the script gave me the correct value ( 61aebf45 )
I wanted to implement a more elegant way with z3Py and I tried the following script :
from z3 import *
hash = BitVec('hash', 32)
s = Solver()
eq1 = ( hash >> 27 | ((hash ^ ord('s')) << 5)) & 0xffffffff
eq2 = ( eq1 ^ (eq1 << 8)) & 0xffffffff
eq3 = ( eq2 >> 27 | ((eq2 ^ ord('k')) << 5)) & 0xffffffff
eq4 = ( eq3 ^ (eq3 << 8)) & 0xffffffff
eq5 = ( eq4 >> 27 | ((eq4 ^ ord('a')) << 5)) & 0xffffffff
eq6 = ( eq5 ^ (eq5 << 8)) & 0xffffffff
eq7 = ( eq6 >> 27 | ((eq6 ^ ord('n')) << 5)) & 0xffffffff
eq8 = ( eq7 ^ (eq7 << 8)) & 0xffffffff
eq9 = ( eq8 >> 27 | ((eq8 ^ ord('d')) << 5)) & 0xffffffff
eq10 = ( eq9 ^ (eq9 << 8)) & 0xffffffff
eq11 = ( eq10 >> 27 | ((eq10 ^ ord('e')) << 5)) & 0xffffffff
eq12 = ( eq11 ^ (eq11 << 8)) & 0xffffffff
eq13 = ( eq12 >> 27 | ((eq12 ^ ord('r')) << 5)) & 0xffffffff
eq14 = ( eq13 ^ (eq13 << 8)) & 0xffffffff
s.add(eq14 == 0)
while s.check() == sat:
m = s.model()
print(m[hash])
s.add(Or(hash != s.model()[hash]))
But no output (unsat problem) and if I modify
hash = BitVec('hash', 32)
to
hash = BitVec('hash', 64)
The script give me a lot of models
Is the problem not solvable or I did a mistake on the code ?

>> translates to arithmetic shift-right; but what you actually meant was logical-shift right. Use LShR instead. That is, replace all instances of:
hash >> 27
with
LShR(hash, 27)
If you do this, it prints 1638842181 which is the value you seem to be looking for.
Note that you don't have to "unroll" the loop yourself; you can just walk over the input string and code this just like you did the original Python; simply keep assigning to the same symbolic value.

Related

I'm trying to extract data from a csv file but I can't exactly get it right

This is what my code should do:
Take a reading with a barcode scanner, it consists of 16-17 string depending on the color palette type.
I segment what i read into smaller parts to process, A, B1, B2, C (the substr works perfectly fine)
I take those substrings and process them into a readable format.
The problem is that I can't (I don't know how to) extract the data correctly so that B2 can be compared to its corresponding colour code and for colorname to be displayed correctly.
Here's a sample of the csv file I'm trying to extract the data from, it consists of multiple rows and two columns:
RAL7016,NEGRO
RAL7017,BLANCO
RAL7018,AZUL
RAL7019,VERDE
YW207F,AZULOSCURO
Y2208I,BEIGE
Y4304I,AMARILLO
YX353F,CIELO
Y2212I,TURQUESA
First row can contain 6 or 7 characters which is why I ask in the code if RAL is present.
If anyone can help me I would really appreciate it. Many thanks.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
main()
{
string scan, A, B1, B2, C;
Init:
int x=0, y=0;
cout << "\nEsperando a scan...";
cin >> scan;
cout << "Codigo:" << scan;
A = scan.substr (0,3);
B1 = scan.substr (3,3);
B2 = scan.substr (6,3);
if (B2 == "RAL") B2 = scan.substr(5,7), C = scan.substr (13,4);
else B2 = scan.substr(5,6), C = scan.substr (12,4);
//Tipo de producto
if (A == "PUE") A = "PUERTA", x=1;
if (A == "PAN") A = "PANEL", x=1;
if (A == "LAC") A = "LACADO", x=1;
if (x=0) A = "PRODUCTO NO AGREGADO AL SISTEMA";
//Tipo de acabado
if (B1 == "BRI") B1 = "BRILLO", x=1;
if (B1 == "TEX") B1 = "TEXTURADO", x=1;
if (B1 == "MAT") B1 = "MATE", x=1;
if (x=0) B1 = "TIPO DE ACABADO NO AGREGADO AL SISTEMA";
//Leer colour desde archivo csv
string colourcode = "blank", colourname = "blank";
ifstream myfile("colourtable.csv");
if(myfile.is_open()){
while(getline(myfile, colourcode, ',') && getline(myfile, colourname)){
if(B2 == colourcode){
if(B2.substr (0,3) == "RAL"){
B2 = colourname.substr(8,20);
}
else B2 = colourname.substr(7,20);
}
}
myfile.close();
}
else B2 = "Falta archivo colourtable.csv";
//Output en pantalla
cout << "\n Producto:" << A << "\n Acabado:" << B1 << "\n colour:" << B2 << "\n N Pedido:" << C << "\n" << "Y = "<< y << "\n";
//colour debug
cout << "\n colourcode:" << colourcode << "\n colourname:" << colourname;
//Output en archivo a pedidos.csv
fstream file;
file.open ("pedidos.csv");
if (file.is_open()){
file << C << "," << B2 << "," << B1;
file.close();
}
else cout << "\n Falta archivo pedidos.csv";
//Reiniciar ciclo
goto Init;
}

Process of operator &, &&, and |

Given the following binary numbers ...
a = 00001100
b = 00011100
t = a & b && a | b;
...what is the value of the following expression?
The answer should be: 00000001, could anyone explain the process to me?
Seems to be language specific: http://en.wikipedia.org/wiki/Order_of_operations#Programming_languages.
I tested it out in C, and got exactly what I (and you) expected:
int a = 0b00011100;
int b = 0b00001100;
printf("%d\n", a & b); // 12
printf("%d\n", a | b); // 28
printf("%d\n", (a & b) && (a | b)); // 1
printf("%d\n", a & b && a | b); // 1

Tweaking a Function in Python

I am trying to get the following code to do a few more tricks:
class App(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.answerLabel = Label(self, text="Output List:")
self.answerLabel.grid(row=2, column=1, sticky=W)
def psiFunction(self):
j = int(self.indexEntry.get())
valueList = list(self.listEntry.get())
x = map(int, valueList)
if x[0] != 0:
x.insert(0, 0)
rtn = []
for n2 in range(0, len(x) * j - 2):
n = n2 / j
r = n2 - n * j
rtn.append(j * x[n] + r * (x[n + 1] - x[n]))
self.answer = Label(self, text=rtn)
self.answer.grid(row=2, column=2, sticky=W)
if __name__ == "__main__":
root = Tk()
In particular, I am trying to get it to calculate len(x) * j - 1 terms, and to work for a variety of parameter values. If you try running it you should find that you get errors for larger parameter values. For example with a list 0,1,2,3,4 and a parameter j=3 we should run through the program and get 0123456789101112. However, I get an error that the last value is 'out of range' if I try to compute it.
I believe it's an issue with my function as defined. It seems the issue with parameters has something to do with the way it ties the parameter to the n value. Consider 0123. It works great if I use 2 as my parameter (called index in the function) but fails if I use 3.
EDIT:
def psi_j(x, j):
rtn = []
for n2 in range(0, len(x) * j - 2):
n = n2 / j
r = n2 - n * j
if r == 0:
rtn.append(j * x[n])
else:
rtn.append(j * x[n] + r * (x[n + 1] - x[n]))
print 'n2 =', n2, ': n =', n, ' r =' , r, ' rtn =', rtn
return rtn
For example if we have psi_j(x,2) with x = [0,1,2,3,4] we will be able to get [0,1,2,3,4,5,6,7,8,9,10,11] with an error on 12.
The idea though is that we should be able to calculate that last term. It is the 12th term of our output sequence, and 12 = 3*4+0 => 3*x[4] + 0*(x[n+1]-x[n]). Now, there is no 5th term to calculate so that's definitely an issue but we do not need that term since the second part of the equation is zero. Is there a way to write this into the equation?
If we think about the example data [0, 1, 2, 3] and a j of 3, the problem is that we're trying to get x[4]` in the last iteration.
len(x) * j - 2 for this data is 10
range(0, 10) is 0 through 9.
Manually processing our last iteration, allows us to resolve the code to this.
n = 3 # or 9 / 3
r = 0 # or 9 - 3 * 3
rtn.append(3 * x[3] + 0 * (x[3 + 1] - x[3]))
We have code trying to reach x[3 + 1], which doesn't exist when we only have indices 0 through 3.
To fix this, we could rewrite the code like this.
n = n2 / j
r = n2 - n * j
if r == 0:
rtn.append(j * x[n])
else:
rtn.append(j * x[n] + r * (x[n + 1] - x[n]))
If r is 0, then (x[n + 1] - x[n]) is irrelevant.
Please correct me if my math is wrong on that. I can't see a case where n >= len(x) and r != 0, but if that's possible, then my solution is invalid.
Without understanding that the purpose of the function is (is it a kind of filter? or smoothing function?), I prickled it out of the GUI suff and tested it alone:
def psiFunction(j, valueList):
x = map(int, valueList)
if x[0] != 0:
x.insert(0, 0)
rtn = []
for n2 in range(0, len(x) * j - 2):
n = n2 / j
r = n2 - n * j
print "n =", n, "max_n2 =", len(x) * j - 2, "n2 =", n2, "lx =", len(x), "r =", r
val = j * x[n] + r * (x[n + 1] - x[n])
rtn.append(val)
print j * x[n], r * (x[n + 1] - x[n]), val
return rtn
if __name__ == '__main__':
print psiFunction(3, [0, 1, 2, 3, 4])
Calling this module leads to some debugging output and, at the end, the mentionned error message.
Obviously, your x[n + 1] access fails, as n is 4 there, so n + 1 is 5, one too much for accessing the x array, which has length 5 and thus indexes from 0 to 4.
EDIT: Your psi_j() gives me the same behaviour.
Let me continue guessing: Whatever we want to do, we have to ensure that n + 1 stays below len(x). So maybe a
for n2 in range(0, (len(x) - 1) * j):
would be helpful. It only produces the numbers 0..11, but I think this is the only thing which can be expected out of it: the last items only can be
3*3 + 0*(4-3)
3*3 + 1*(4-3)
3*3 + 2*(4-3)
and stop. And this is achieved with the limit I mention here.

Code Golf: Connecting the dots

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
You may remember these drawings from when you were a child, but now it's time to let the computer draw them (in full ascii splendour). Have fun!
Description:
The input are multiple lines (terminated by a newline) which describe a 'field'. There are 'numbers' scattered across this field (seperated by whitespace). All lines can be considered to be the same length (you can pad spaces to the end).
the numbers always start at 1
they follow the ordering of the natural numbers: every 'next number' is incremented with 1
every number is surrounded by (at least) one whitespace on its left and right
Task:
Draw lines between these numbers in their natural order
(1 -> 2 -> 3 -> ...N) (assume N <= 99) with the following characteristics:
replace a number with a '+' character
for horizontal lines: use '-'
for vertical lines: use '|'
going left and down or right and up: /
going left and up or right and down: \
Important notes:
When drawing lines of type 4 and 5 you can assume (given the points to connect with coordinates x1, y1 and x2, y2) that distance(x1,x2) == distance(y1,y2). Or in other words (as user jball commented): "consecutive elements that are not horizontally or vertically aligned always align to the slope of the slash or backslash".
It is important to follow the order in which the dots are connected (newer lines can strike out older lines).
-- Sample input 1 --
8
7 6
10 9
5
3 4
11
12 13
1 2
-- Sample output 1 --
+
/|
/ +--+
+--------+ \
/ \
/ +
/ |
/ +--+
+ |
\ |
+------------------------+
+--------------------------+
-- Sample input 2 --
64
63
62 61
1 65
66 57 58
2 56 59 45
67 55 46
3 44
54 60 47
53 52 49 48
4 51 50 43
5 42
41
6 23
22 25 26 40
20 21 24 34
7 13 12 33
19 27 32
14 35
8 15
16
39
17 18 28 31 36
9 38
10 11 29 30 37
-- Sample output 2 -- (unicorn reference)
+
/+
//
//
//
/+--+
+ + \
| + +-\+
+ \ + \ +
/ + + \ +\
+ \ \ | +
| + + +/
| +--+ +-------+/
+ +--+ +
/ \
+ +
| +
+ + /
\ +\ +---+ +
\ +--+ + \ /+
+ +--+ / \ /+|
/ | |+ + /+ |
/ + || / // +
+ + || / // /
\ + || / // /
\ | || / +/ /
\ +---+ + +\ +
+ | | | +|
+--+ +---+ +
Winner:
Shortest solution (by code character count). Input can be read via standard input.
Commodore 64 BASIC - 313 chars
EDIT: See below for the golfed version
A little trip down the memory lane with PET graphics, POKEs and PEEKs and everything :)
The program operates directly in the screen memory, so you just go ahead, clear the screen, place your dots, and type RUN:
You have to wait a minute or so while it finds the dots and then it starts to draw. It isn't fast - you can actually see the lines being drawn, but that's the coolest part :)
Golfed version:
Commodore BASIC seems like a great language for golfing, because it doesn't require whitespace :) You can also shorten most of the commands by entering an unshifted first letter followed by a shifted second letter. For example, POKE can be typed as P[SHIFT+O], which appears as P┌ on the screen:
Perl, 222 char (211)
Perl, 384 365 276 273 253 225 222 218 211 chars (222 when contest ended). Newlines are for "readability" only and are not included in the character count.
Last edit: no longer overwriting $", and printing #S directly
$_=join'',#S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>;
while(/\b$n /){$S[$q=$-[0]]='+';($P,$Q)=sort{$a-$b}$q,$p||$q;
for(qw'\98 |97 /96 -1'){/\D/;$S[$P]=$&until($Q-$P)%$'||$Q<=($P+=$')}
$n++;$p=$q}s/\d/ /,print for#S
Explanation:
$_=join'',#S=map{$n=s/$/$"x97/e;(/./g)[0..95],$/}<>;
This task will be easier if all the lines are the same length (say, 97 characters).
This statement takes each line of input, replaces the end-of-line character with
96 spaces, then pushes the first 96 characters plus a newline into the array #S.
Note we are also setting $n=1, as 1 is the first number we'll look for in
the input.
The join statement creates a single string from the array #S.
It is more convenient to use the scalar variable $_ for pattern matching, and more convenient to use the array #S for making updates to the picture.
while(/\b$n /){
Search for the number $n in the variable $_. Evaluating regular expressions in Perl
has several side-effects. One is to set the special variable $-[0] with the position of the start of the matched pattern within the matched string. This gives us the position of the number $n in the string $_ and also the array #S.
Of course, the loop will end when $n is high enough that we can't find it in the input.
$S[$q=$-[0]]='+';
Let $q be the position of the number $n in the string $_ and the array #S,
and assign the character '+' at that position.
$P=($p||=$q)+$q-($Q=$q>$p?$q:$p)
($P,$Q)=sort{$a-$b}$p||$q,$q;
The first time through the loop, set $p to $q. After the
first time, $p will hold the previous value of $q (which
will refer to the position in the input of the previous number).
Assign $P and $Q such that $P=min($p,$q),
$Q=max($p,$q)
for(qw'\98 |97 /96 -1'){
By construction, consecutive numbers are either
connected by a vertical line. Since the input is constructed
to have 97 characters on each line, this case means that
$p-$q is divisible by 97.
"aligned to the slope of a backslash", which would make
$p-$q divisible by 98
"aligned to the slope of a forward slash", which would make
$p-$q divisible by 96
on the same horizontal line
The elements of this list encode the possible number of positions
between line segments, and the character to encode that segment.
/\D/;
Another trivial regex evaluation. As a side-effect, it sets the
special variable $& (the MATCH variable) to the line segment
character (\ | / or -) and $' (the POSTMATCH variable) to
the number (98 97 96 or 1) encoded in the list element.
$S[$P]=$&until($Q-$P)%$'||$Q<=($P+=$')
This statement draws the line segment between two numbers.
If $Q-$P is divisible by $', then keep incrementing $P by $'
and assigning the character $& to $S[$P] until $P reaches $Q.
More concretely, for example if $Q-$P is divisible by 97, then
increment $P by 97 and set $S[$P]='|'. Repeat until $P>=$Q.
$n++;$p=$q
Prepare for the next iteration of the loop. Increment $n to the
next number to search for in the input, and let $p hold the
position of the previous number.
s/\d/ /,print for#S
Output the array, converting any leftover digits (from double
digit identifiers in the input where we only overwrote the first
digit with a '+') to spaces as we go.
MS-DOS Batch (yes, you read right!)
I often hear (or read) people say batch isn't very powerful and you can't do much with them, well to them I say, behold, the power of BATCH!
The actual script (script.bat):
set file=%~1
call :FindNextNum 1
for /F "tokens=2 delims=:" %%i IN ('find /c /V "" "%file%"') DO set /a totalLines=%%i
set maxLen=0
for /F "delims=" %%i IN (%file%) DO (
call :CountChars "%%i"
if /i !charCount! gtr !maxLen! set maxLen=!charCount!
)
for /L %%i IN (0,1,%totalLines%) DO set "final_%%i=" & for /L %%j IN (0,1,%maxLen%) DO set "final_%%i=!final_%%i! "
:MainLoop
set currLineNum=%lineNum%
set currCol=%linePos%
set currNum=%nextNum%
set /a targetNum=%currNum%+1
call :FindNextNum %targetNum%
if "%nextNum%"=="" goto MainEnd
REM echo %currNum% -^> %nextNum%
if /I %currLineNum% lss %lineNum% (
call :DrawLine %currCol% %currLineNum% %linePos% %lineNum%
) else (
call :DrawLine %linePos% %lineNum% %currCol% %currLineNum%
)
goto MainLoop
:MainEnd
for /L %%i IN (0,1,%totalLines%) DO echo.!final_%%i!
goto:eof
:DrawLine
if /I %2 equ %4 goto:DrawHoriz
set "char=" & set "pos=%1" & set "inc=0"
if /I %1 LSS %3 set "char=\" & set "pos=%1" & set "inc=1"
if /I %1 GTR %3 set "char=/" & set "pos=%1" & set "inc=-1"
for /L %%i IN (%2,1,%4) DO call :DrawChar %%i !pos! %char% & set /a "pos+=%inc%"
goto:DrawEnds
:DrawHoriz
set "start=%1+1" & set "end=%3"
if /I %start% gtr %end% set "start=%3+1" & set "end=%1"
set /a lineEnd=%end%+1
set lineEnd=!final_%2:~%lineEnd%!
for /L %%i IN (%start%,1,%end%) DO set final_%2=!final_%2:~0,%%i!-
set final_%2=!final_%2!!lineEnd!
:DrawEnds
call :DrawChar %2 %1 +
call :DrawChar %4 %3 +
goto:eof
:DrawChar
set /a skip2=%2+1
if "%3"=="" (
set final_%1=!final_%1:~0,%2!^|!final_%1:~%skip2%!
) else (
set final_%1=!final_%1:~0,%2!%3!final_%1:~%skip2%!
)
goto:eof
:CountChars
set charCount=0
set val=%~1
:CountChars_loop
if not "%val:~1%"=="" (
set /a charCount+=1
set val=!val:~1!
goto CountChars_loop
)
goto:eof
:FindNextNum
for /F "delims=" %%i IN ('type "%file%" ^| find /V /N ""') DO (
for /F "tokens=1,2 delims=[]" %%j IN ("%%i") DO (
set /a lineNum=%%j-1
call :FindNext_internal "%%k" %1
if /I !nextNum! equ %1 goto :eof
)
)
goto:eof
:FindNext_internal
set currLine=%~1
set linePos=0
:FindNext_internal_loop
call :NextNumInLine "%currLine%"
set /a linePos+=%spaceInterval%
if "%nextNum%"=="" goto :EOF
if /I %nextNum% equ %2 goto :EOF
set /a spaceInterval+=1
set /a linePos+=1
if /I %nextNum% GTR 9 set /a "spaceInterval+=1" & set /a linePos+=1
set currLine=!currLine:~%spaceInterval%!
goto FindNext_internal_loop
:NextNumInLine
set nextNum=
for /F %%i IN (%1) DO set /a nextNum=%%i
if "%nextNum%"=="" goto :eof
set /a spaceInterval=0
set val=%~1
:NextNumInLine_loop
if "%val:~0,1%"==" " (
set /a spaceInterval+=1
set val=!val:~1!
goto NextNumInLine_loop
)
goto :eof
And this is how you call it
echo off
setlocal ENABLEDELAYEDEXPANSION
call script.bat input.txt
where "input.txt" is a file that contains the input for the "program".
P.S. This isn't actually optimized for line length yet, I've already spent a couple of hours getting to this point and now I need to sleep... I'll see if I can improve it tomorrow (currently 'script.bat' sits at 2755 bytes)
Rebmu: 218 chars
Ma L{-|\/}Qb|[sg?SBaB]Da|[feSm[TfiSrj[spAsp]iT[++Tbr]]t]Xa|[i?A]Ya|[i?FImHDa]Ca|[skPCmSCaBKfsA]wh[Jd++N][roG[xJyJ]]Bf+GwhB[JcB Ff+GiF[KcF HqXkXj VqYkYju[chCbPClEZv1[ezH2[eeHv3 4]]e?A+bRE[hV]f]]chJeFIlSCj{+}{+ }Jk Bf]wM
I'm getting pretty good at reading and editing it natively in its pig-latin form. (Though I do use line breaks!!) :)
But here's how the dialect is transformed by the interpreter when the case-insensitive "mushing" trick is boiled away, and one gets accustomed to it. I'll add some comments. (Tips: fi is find, fe is foreach, sp is a space character, i? is index, hd is head, ch is change, sk is skip, pc is pick, bk is break, i is if, e is either, ee is either equal, ad nauseum)
; copy program argument into variable (m)atrix
m: a
; string containing the (l)etters used for walls
l: {-|\/}
; q is a "b|function" (function that takes two parameters, a and b)
; it gives you the sign of subtracting b from a (+1, -1, or 0)
q: b| [sg? sb a b]
; d finds you the iterator position of the first digit of a two digit
; number in the matrix
d: a| [fe s m [t: fi s rj [sp a sp] i t [++ t br]] t]
; given an iterator position, this tells you the x coordinate of the cell
x: a| [i? a]
; given an iterator position, this tells you the y coordinate of the cell
y: a| [i? fi m hd a]
; pass in a coordinate pair to c and it will give you the iterator position
; of that cell
c: a| [sk pc m sc a bk fr a]
; n defaults to 1 in Rebmu. we loop through all the numbers up front and
; gather their coordinate pairs into a list called g
wh [j: d ++ n] [ro g [x j y j]]
; b is the (b)eginning coordinate pair for our stroke. f+ returns the
; element at G's current position and advances G (f+ = "first+")
; advance g's iteration position
b: f+ g
wh b [
; j is the iterator position of the beginning stroke
j: c b
; f is the (f)inishing coordinate pair for our stroke
f: f+ g
; if there is a finishing pair, we need to draw a line
i f [
; k is the iterator position of the end of the stroke
k: c f
; the (h)orizontal and (v)ertical offsets we'll step by (-1,0,1)
h: q x k x j
v: q y k y j
u [
; change the character at iterator location for b (now our
; current location) based on an index into the letters list
; that we figure out based on whether v is zero, h is zero,
; v equals h, or v doesn't equal h.
ch c b pc l ez v 1 [ez h 2 [ee h v 3 4]]
; if we update the coordinate pair by the offset and it
; equals finish, then we're done with the stroke
e? a+ b re [h v] f
]
]
; whether we overwrite the number with a + or a plus and space
; depends on whether we detect one of our wall "letters" already
; one step to the right of the iterator position
ch j e fi l sc j {+} {+ }
; update from finish pair to be new begin pair for next loop iteration
j: k
b: f
]
; write out m
w m
Both the language and sample are new and in an experimental stage. For instance, ad couldn't be used to add together vectors and matrices before I changed it to help with this sample. But I think that's just the sort of thing that a language designed specifically for code golf has to have anyway. It's a subtle line between "language" and "library".
Latest source with comments available on GitHub
Haskell, 424 chars
Current char count: 424 430 451 466 511 515 516 518 525 532 541 545 550 556 569 571 577 582 586 592.
import List
x%c=[(i,c)|i<-x]
l k p q|p>q=l k q p|True=head[[p,p+j..q]%c|m<-zip[k-1,k,k+1,1]"/|\\-",let (j,c)=m,mod(q-p)j==0]
w=map snd
q(k,m,x)z=w$sort$nubBy((==)&fst)$x%'+'++(concat$zipWith(l k)x$tail x)++z%'\n'++[1..m]%' '
r(z,m,x)=q(last z,m-1,w$sort x)z
u[(m,_)]n x=(-m::Int,n):x;u _ _ x=x
t(z,n,x)s|s=="\n"=(n:z,n+1,x)|True=(z,n+length s,u(reads s)n x)
y&x=(.x).y.x
main=interact$r.foldl t([],1,[]).groupBy((&&)&(>' '))
This version takes a lot of inspiration from the original Haskell entry below, but makes some significant changes. Most importantly, it represents image locations with a single index, not a pair of coordinates.
There are some changes:
The input must now have all lines padded to the same length (allowed by the rules.)
No longer needs either language extension
Original version:
(Needs -XTupleSections, and maybe -XNoMonomorphismRestriction)
import List
b=length
f=map
g=reverse
a(x,y)" "=(x,y+1)
a(x,y)z=([y,read z]:x,y+b z)
x%y=[min x y+1..max x y-1]
j([x,y],[w,z])|y==z=f(,'-')$f(y,)$x%w|x==w=f(,'|')$f(,x)$y%z|(y<z)==(x<w)=f(,'\\')$zip(y%z)$x%w|True=f(,'/')$zip(y%z)$g$x%w
k 0='\n'
k _=' '
y&x=(.x).y.x
y?x=f y.sort.x.concat
r z=snd?(nubBy((==)&fst).g)$[((y,x),k x)|x<-[0..maximum$f b d],y<-[1..b d]]:[((y,x),'+')|[x,y]<-e]:(f j$zip e$tail e)where d=f(groupBy$(&&)&(>' '))$lines z;e=tail?f g$zipWith(f.(:))[1..]$f(fst.foldl a([],1))d
main=interact r
Explanation:
(1) d=...: Splits the input into spaces and numbers, e.g.
z = " 6 5\n\n1 2\n\n 4 3\n\n 7"
=> d = [[" ","6"," "," ","5"],[],["1"," "," "," "," "," "," "," ","2"],[],[" "," "," "," ","4"," "," "," ","3"],[],[" ","7"]]
(2) e=...: Converts d into a list of (y, x) coordinates for each number.
e = [[1,3],[9,3],[9,5],[5,5],[5,1],[2,1],[2,7]]
--- // 1 2 3 4 5 6 7
(3)
[((y,x),k x)|...] is an empty board. (k returns a space or a \n depending on the x-coordinate.)
[((y,x),'+'))|...] are the plus signs at the numbers.
(f j$zip e$tail e) are the lines connecting the numbers. (j maps a pair of coordinates into a list of (coordinate, character) which represents a line.)
These 3 components are concatenated and filtered to form the actual output. Note that the order is important, so that nubBy(...).g can only keep the last character in the same location.
AWK - 296 317 321 324 334 340
Not a prize winner (yet), but I am pleased with the effort (line breaks for display). This new version uses VT-100 escape sequences. The '^[' is just one character, Escape!!! Cut and paste will not work with this version, since the sequence "^[" has to be replaced with the real ESC character. To make it forum friendly, ESC could be specified as "\0x1b", but it takes too much space...
BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR;
m=m>k?m:k}}}END{printf"^[[2J[%d;%dH+",Y=y[i=1],X=x[1];while(a=x[++i])
{a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;
for(r=a?a*A:b*B;--r;){printf"^[[%d;%dH%c",Y+=B,X+=A,t}
printf"^[[%d;%dH+",Y+=B,X+=A}}
The older standard version
BEGIN{FS="[ ]"}{for(j=i=0;i<NF;j+=length(g)){if(g=$++i){x[g]=k=i+j;y[g]=NR;
m=m>k?m:k}}}END{q[X=x[1],Y=y[i=1]]=43;while(a=x[++i]){a-=X;b=y[i]-Y;
t=a?b?a*b>0?92:47:45:124;A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;for(r=a?a*A:b*B;--r;
q[X+=A,Y+=B]=t);q[X+=A,Y+=B]=43}for(j=0;++j<NR;){for(i=0;i<m;){t=q[i++,j];
printf"%c",t?t:32}print}}
Now a little explanation
# This will break the input in fields separated by exactly 1 space,
# i.e. the fields will be null or a number.
BEGIN{FS="[ ]"}
# For each line we loop over all fields, if the field is not null
# it is a number, hence store it.
# Also account for the fact the numbers use space.
# Also, find the maximum width of the line.
{
for(j=i=0;i<NF;j+=length(g)){
if(g=$++i){
k=j+i;x[g]=k;y[g]=NR;m=m>k?m:k
}
}
}
# Once we have all the data, let start cooking.
END{
# First, create a matrix with the drawing.
# first point is a +
q[X=x[1],Y=y[i=1]]=43;
# loop over all points
while(a=x[++i]){
# Check next point and select character
# If a == 0 -> -
# If b == 0 -> |
# If a and b have same sign -> \ else /
a-=X;b=y[i]-Y;t=a?b?a*b>0?92:47:45:124;
# there is no sgn() function
A=a?a>0?1:-1:0;B=b?b>0?1:-1:0;
# Draw the line between the points
for(k=0;++k<(a?a*A:b*B);){
q[X+=A,Y+=B]=t
}
# store + and move to next point
q[X+=A,Y+=B]=43
}
# Now output all lines. If value in point x,y is 0, emit space
for(j=0;++j<NR;){
for(i=0;i<m;){
t=q[i++,j];printf("%c",t?t:32)
}
print
}
}
C, 386
402 386 character in C. Newlines after the first are only for readability.
#include <stdio.h>
int x[101],y[101],c=1,r,w,h,b,i,j,k,m,n;
int main(){
while((b=getchar())-EOF)
b-' '?b-'\n'?ungetc(b,stdin),scanf("%d",&b),x[b]=c++,y[b]=h,c+=b>9:(w=c>w?c:w,++h,c=1):++c;
for(r=0;r<h&&putchar('\n');++r)
for(c=0;c<w;++c){
for(b=' ',i=2,m=x[1]-c,n=y[1]-r;j=m,k=n,m=x[i]-c,n=y[i]-r,x[i++];)
b=j|k&&m|n?j*m>0|k|n?k*n<0?(j-k|m-n?j+k|m+n?j|m?b:'|':'/':'\\'):b:'-':'+';
putchar(b);
}
}
Intel Assembler
Assembled size: 506 bytes
Source: 2252 bytes (hey, it's not a trivial problem this one)
To Assemble: Use A86
To Run: Tested with a WinXP DOS box. Invocation jtd.com < input > output
mov ax,3
int 10h
mov ax,0b800h
mov es,ax
mov ah,0bh
int 21h
mov bx,255
cmp al,bl
mov dh,bh
mov si,offset a12
push offset a24
je a1
mov si,offset a14
a1: inc bl
a2: mov dl,255
call si
cmp al,10
jb a4
a3: cmp al,10-48
jne a1
inc bh
mov bl,dh
jmp a2
a4: mov dl,al
call si
cmp al,10
jae a5
mov ah,dl
aad
mov dl,al
a5: mov di,dx
mov ch,al
shl di,2
mov [di+a32],bx
cmp bl,[offset a30]
jb a6
mov [offset a30],bl
a6: cmp bh,[offset a31]
jb a7
mov [offset a31],bh
a7: push offset a19
mov al,80
mul bh
add al,bl
adc ah,0
add ax,ax
lea di,[di+2+a32]
mov [di],ax
add di,2
cmp di,[a22-3]
jbe a8
mov [a22-3],di
mov [a25-3],di
a8: mov di,ax
mov al,dl
aam
cmp ah,0
je a10
a9: add ah,48
mov es:[di],ah
add di,2
a10:add al,48
mov es:[di],al
mov al,ch
inc bl
jmp a3
a11:jmp si
a12:mov ah,0bh
int 21h
cmp al,255
jne a15
mov ah,8
int 21h
a13:cmp al,13
je a11
sub al,48
ret
a14:mov ah,1
int 21h
cmp al,26
jne a13
mov si,offset a15
ret
a15:cmp dl,255
je a16
mov al,32
ret
a16:mov si,offset a32 + 4
lodsw
mov cx,ax
mov dx,ax
lodsw
mov di,ax
mov b es:[di],1
mov bp,0f000h
call a26
add sp,6
mov bx,[a22-3]
mov ax,[offset a31]
inc ax
a17:mov bp,[offset a30]
a18:mov b[bx],32
inc bx
dec bp
jnz a18
mov w[bx],0a0dh
add bx,2
dec ax
jnz a17
mov b[bx],'$'
add w[a30],2
a19:lodsw
xchg ax,dx
cmp ah,dh
lahf
mov bl,ah
cmp al,dl
lahf
shr bl,6
shr ah,4
and ah,12
or bl,ah
mov bh,0
shl bx,3
a20:mov b es:[di],43
a21:mov al,b[a30]
mul ch
add al,cl
adc ah,0
mov bp,ax
mov b[bp+100h],43
a22:add di,[bx + a29]
add cl,[bx + a29 + 4]
add ch,[bx + a29 + 6]
mov b es:[di],1
mov al,[bx + a29 + 2]
mov [a21-1],al
mov [a22-1],al
mov bp,01000h
call a26
cmp di,[si]
jne a20
mov al,es:[di+2]
sub al,48
cmp al,10
jae a23
mov b es:[di+2],0
a23:mov b[a21-1],43
mov b[a22-1],43
mov b es:[di],43
lodsw
ret
a24:mov al,b[a30]
mul ch
add al,cl
adc ah,0
mov bp,ax
mov b[bp+100h],43
a25:mov dx,[a22-3]
mov ah,9
int 21h
ret
a26:pusha
a27:mov cx,0ffffh
a28:loop a28
dec bp
jnz a27
popa
ret
a29:dw -162,92,-1,-1,-2,45,-1,0,158,47,-1,1,0,0,0,0,-160,124,0,-1
a30:dw 0
a31:dw 0,0,0,160,124,0,1,0,0,0,0,-158,47,1,-1,2,45,1,0,162,92,1,1
a32:
Interesting features: self modifying code, animated output (the second example works, but is too big to display), abuse of 'ret' to implement a loop counter, interesting way of determining line/movement direction.
F#, 725 chars
open System
let mutable h,s,l=0,Set.empty,Console.ReadLine()
while l<>null do
l.Split([|' '|],StringSplitOptions.RemoveEmptyEntries)
|>Seq.iter(fun t->s<-s.Add(int t,h,(" "+l+" ").IndexOf(" "+t+" ")))
h<-h+1;l<-Console.ReadLine()
let w=Seq.map(fun(k,h,x)->x)s|>Seq.max
let o=Array2D.create h (w+1)' '
Seq.sort s|>Seq.pairwise|>Seq.iter(fun((_,b,a),(_,y,x))->
let a,b,x,y=if b>y then x,y,a,b else a,b,x,y
o.[b,a]<-'+'
o.[y,x]<-'+'
if b=y then for x in(min a x)+1..(max a x)-1 do o.[y,x]<-'-'
elif a=x then for h in b+1..y-1 do o.[h,x]<-'|'
elif a<x then for i in 1..y-b-1 do o.[b+i,a+i]<-'\\'
else for i in 1..y-b-1 do o.[b+i,a-i]<-'/')
for h in 0..h-1 do
for x in 0..w do printf"%c"o.[h,x]
printfn""
Legend:
h = height
s = set
l = curLine
w = (one less than) width
o = output array of chars
Lines 1-6: I keep a set of (number, lineNum, xCoord) tuples; as I read in each line of input I find all the numbers and add them to the set.
Line 7-8: Then I create an array of output chars, initialized to all spaces.
Line 9: Sort the set (by 'number'), then take each adjacent pair and ...
Lines 10-16: ... sort so (a,b) is the 'highest' of the two points and (x,y) is the other. Put the '+' signs, and then if horizontal, draw that, else if vertical, draw that, else draw the correct diagonal. If the input is not 'valid', then who knows what happens (this code was littered with 'asserts' before I golf-ized it).
Lines 17-19: Print the result
Powershell, 328 304 characters
$i=$l=0;$k=#{}
$s=#($input|%{[regex]::matches($_,"\d+")|%{$k[1*$_.Value]=#{y=$l
x=$_.Index}};$l++;""})
while($a=$k[++$i]){
if($i-eq1){$x=$a.x;$y=$a.y}
do{$d=$a.x.CompareTo($x);$e=$a.y.CompareTo($y)
$s[$y]=$s[($y+=$e)].PadRight($x+1).Remove($x,1).Insert(($x+=$d),
"\-/|+|/-\"[4+$d*3+$e])}while($d-or$e)}$s
and here's a pretty-printed version with comments:
# Usage: gc testfile.txt | dots.ps1
$l=$i=0 # line, dot index (used below)
$k=#{} # hashtable that maps dot index to coordinates
# Apply regular expression to each line of the input
$s=#( $input | foreach{
[regex]::matches($_,"\d+") | foreach{
# Store each match in the hashtable
$k[ 1*$_.Value ] = #{ y = $l; x = $_.Index }
}
$l++; # Next line
"" # For each line return an empty string.
# The strings are added to the array $s which
# is used to produce the final output
}
)
# Connect the dots!
while( $a = $k[ ++$i ] )
{
if( $i -eq 1 ) # First dot?
{
# Current position is ($x, $y)
$x = $a.x;
$y = $a.y
}
do
{
$d = $a.x.CompareTo( $x ) # sign( $a.x - $x )
$e = $a.y.CompareTo( $y ) # sign( $a.y - $y )
$c = '\-/|+|/-\'[ 4 + $d * 3 + $e ] # character '
# Move
$x += $d
$y += $e
# "Replace" the charcter at the current position
# PadRight() ensures the string is long enough
$s[ $y ]=$s[ $y ].PadRight( $x+1 ).Remove( $x, 1 ).Insert( $x, $c )
} while( $d -or $e ) # Until the next dot is reached
}
# Print the resulting string array
$s
Python - 381
import re
b=list(iter(raw_input,''))
c=sum((zip([i]*999,re.finditer('\\d+',x))for i,x in enumerate(b)),[])
d=sorted((int(m.group()),i,m.start())for i,m in c)
e=[[' ']*max(map(len,b))for x in b]
for(t,u,v),(x,y,z)in zip(d,d[1:]+d[-1:]):
e[u][v]='+'
while u!=y or v!=z:i,j=(u<y)-(u>y),(v<z)-(v>z);u+=i;v+=j;e[u][v]=['|','/\\-'[(i==j)+2*(i==0)]][j!=0]
print'\n'.join(map(''.join,e))
C#, 422 chars
758 754 641 627 584 546 532 486 457 454 443 440 422 chars (next time maybe I won't submit so soon.)
using A=System.Console;class B{static int C,o,d,e,G,O=1,f,F,u,n;static
void Main(){var s=A.In.ReadToEnd();A.Clear();while(++u<s.Length){f++;if
(s[u]<32){u++;F++;f= 0;}if(s[u]>32){if(int.Parse(s[u]+""+s[++u])==O){o=
e>f?1:f>e?-1:0;C=d>F?1:F>d?-1:0 ;G=e+o;n=d+C;if(O++>1)while(n!=F||G!=f)
{A.SetCursorPosition(G-=o,n-=C);A.Write( "+/-|\\"[n==d&&G==e?0:n==F&&G
==f?0:C+o==0?1:C==0?2:o==0?3:4]);}e=f;d=F;F=0;f=u=-1 ;}f++;}}A.Read();}}
Usage: run, paste (or type) the input, ensure the last line is terminated, press CTRL-Z or F6, press Enter.
Formatted but still basically unintelligable version:
using A = System.Console;
class B
{
// code golf fun!
static int C, o, d, e, G, O = 1, f, F, u, n;
static void Main()
{
// read the input into a string char by char until EOF
var s = A.In.ReadToEnd();
A.Clear(); // clear console, ready to draw picture
// O is the "dot" number we're looking for
// f is current column
// F is current row
// loop over the field looking for numbers sequentially
// until no more are found
while (++u < s.Length)
{
f++;
// any char <32 is expected to be a CR/LF
// increment the current row and reset the current column
if (s[u] < 32)
{
u++; // skip the other half of the CR/LF pair
F++; // next row
f = 0; // column reset
}
// any char >32 is expected to be a number
if (s[u] > 32)
{
// parse the current + next char and see if it's
// the number we want
if (int.Parse(s[u] + "" + s[++u]) == O)
{
// set up coordinates, compare X1 with X2
// and Y1 with Y2 to figure out line direction
// horizontal direction (same as o=e.CompareTo(f))
o = e > f ? 1 : f > e ? - 1 : 0;
// vertical direction (same as C=d.CompareTo(F))
C = d > F ? 1 : F > d ? - 1 : 0;
// initial offsets compensate for off-by-one
G = e + o;
n = d + C;
// draw the line (except for the very first dot)
if (O++ > 1)
while (n != F || G != f)
{
// update coords and write desired char
A.SetCursorPosition(G -= o, n -= C);
// this lovely line decides which char to
// print, and prints it
A.Write(
"+/-|\\"[n == d && G == e ? 0 : n == F && G
== f ? 0 : C + o == 0 ? 1 : C == 0 ? 2 : o
== 0 ? 3 : 4]);
}
// remember end point of this line, to use as start point
// of next line
e = f;
d = F;
// reset current row (F), column (f), field position (u)
F = 0;
f = u = -1;
}
// bump current column because we parse 2 chars when we
// find a dot
f++;
}
}
A.Read(); // prevent command prompt from overwriting picture
}
}
Here goes!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sign(int x) {
if (x < 0)
return -1;
if (x > 0)
return +1;
return 0;
}
#define MAX_ROWS 100
#define MAX_COLS 100
#define MAX_DIGITS 100
int main(void)
{
// Read in the digits
int number[MAX_DIGITS][2];
int rows = 0;
int cols = 0;
char row[MAX_COLS];
int maxvalue = 0;
int i, j, value, x;
for (i = 0; i < MAX_ROWS; i++) {
if (row != fgets(row, MAX_COLS, stdin))
break;
value = 0;
for (j=0; row[j] != 0; j++) {
if (row[j] >= '0' && row[j] <= '9') {
x = j;
value = 0;
do {
value = 10*value + (row[j]-'0');
j++;
} while (row[j] >= '0' && row[j] <= '9');
number[value][0] = i;
number[value][1] = x;
if (maxvalue < value) maxvalue = value;
if (rows < i+1) rows = i+1;
if (cols < x+1) cols = x+1;
}
}
}
// Create an empty field
char field[rows][cols];
memset(field, ' ', rows*cols);
char lines[] = "\\|/-+-/|\\";
int dr,dc;
// Draw the numbers and lines
field[number[1][0]][number[1][1]] = '+';
for (i = 2; i <= maxvalue; ++i) {
int r = number[i-1][0];
int c = number[i-1][1];
int rt = number[i][0];
int ct = number[i][1];
dr = sign(rt-r);
dc = sign(ct-c);
char line = lines[(dr+1)*3+dc+1];
while (r != rt || c != ct) {
r += dr;
c += dc;
field[r][c] = line;
}
field[r][c] = '+';
}
for (i = 0; i < rows; ++i) {
for (j = 0; j < cols; ++j)
putchar(field[i][j]);
putchar('\n');
}
return 0;
}
C#, 638 chars
using System;
using System.Linq;
using System.Text.RegularExpressions;
class C
{
static void Main()
{
int i=0,j;
var p = Console.In.ReadToEnd()
.Split('\n')
.SelectMany(
r =>
{
i++; j =0;
return Regex.Matches(r, "\\s+(\\d+)").Cast<Match>()
.Select(m => { j += m.Length; return new { X = j, Y = i-1, N = int.Parse(m.Groups[1].Value) }; });
}
).OrderBy(a=>a.N).ToList();
var W = p.Max(a => a.X)+1;
var k = new char[W*i+W];
i = 0;
while (i < p.Count)
{
var b = p[i > 0 ? i - 1 : 0]; var a = p[i];
int h = a.Y - b.Y, w = a.X - b.X;
var s = "|-/\\"[h == 0 ? 1 : w == 0 ? 0 : h / w > 0 ? 3 : 2];
while ((h | w) != 0) { k[b.X + w + W * (b.Y + h)] = s; h -= h.CompareTo(0); w -= w.CompareTo(0); }
k[a.X + a.Y * W] = '+';
k[W * ++i] = '\n';
}
Console.Write(k);
}
}
I cannot do multi-line in a comment, so I will demonstrate here.
In the following examples, distance(x1,x2) == distance(y1,y2):
+
|\
+-+
+
|\
| \
+--+
+
|\
| \
| \
+---+
With the rules as explained, distance(x1,x2) == distance(y1,y2)+2:
+\
| \
+--\+
+\
| \
| \
+---\+
+\
| \
| \
| \
+----\+
C++ 637
#include <iostream>
#include <string>
#include <vector>
#define S(x)((x)<0?-1:x>0?1:0)
using namespace std;enum{R=100,C=100,D=100};int main(){string s;
int N[D][2],M=0,q=0,p=0,i,j,V,L,a,b;for(i=0;j=0,(i<R)&&getline(cin,s);i++)
while((j=s.find_first_not_of(" ",j))<=s.size()){L=sscanf(&s[j],"%d",&V);
N[V][0]=i;N[V][1]=j;if(M<V)M=V;if(q<=i)q=i+1;if(p<=j)p=j+1;j+=L+1;}
string F(q*p,' '),l="\\|/-+-/|\\";F[p*N[1][0]+N[1][1]]='+';for(i=2;i<=M;++i){
int r=N[i-1][0],c=N[i-1][1],d=N[i][0],e=N[i][1];for(a=S(d-r),b=S(e-c);r!=d||c!=e;)
r+=a,c+=b,F[p*r+c]=l[(a+1)*3+b+1];F[p*r+c]='+';}for(i=0;i<q;i++)
cout<<string(&F[i*p],p)+"\n";}
Indented, and with a few slightly more meaningful names, that looks like:
#include <iostream>
#include <string>
#include <vector>
#define S(x)((x)<0?-1:x>0?1:0)
using namespace std;
enum{R=100,C=100,D=100};
int main(){
string s;
int N[D][2],M=0,rs=0,cs=0,i,j,V,L,dr,dc;
for(i=0;j=0,(i<R)&&getline(cin,s);i++)
while((j=s.find_first_not_of(" ",j))<=s.size()){
L=sscanf(&s[j],"%d",&V);
N[V][0]=i;
N[V][1]=j;
if(M<V)M=V;
if(rs<=i)rs=i+1;
if(cs<=j)cs=j+1;
j+=L+1;
}
string F(rs*cs,' '),lines="\\|/-+-/|\\";
F[cs*N[1][0]+N[1][1]]='+';
for(i=2;i<=M;++i){
int r=N[i-1][0],c=N[i-1][1],rt=N[i][0],ct=N[i][1];
for(dr=S(rt-r),dc=S(ct-c);r!=rt||c!=ct;)
r+=dr,c+=dc,F[cs*r+c]=lines[(dr+1)*3+dc+1];
F[cs*r+c]='+';
}
for(i=0;i<rs;i++)
cout<<string(&F[i*cs],cs)+"\n";
}
Despite superficial differences, it's a blatant theft of morotspaj's code.

How to get checksums for strided patterns

I have a 64 bit number (but only the 42 low order bits are used) and need to computer the sum of the 4 bits at n, n+m, n+m*2 and n+m*3 (note: anything that can produce a sum >4 is invalid) for some fixed m and every value of n that places all the bits in the number
as an example using m=3 and given the 16-bit number
0010 1011 0110 0001
I need to compute
2, 3, 1, 2, 3, 0, 3
Does anyone have any (cool) ideas for ways to do this? I'm fine with bit twiddling.
My current thought is to make bit shifted copies of the input to align the values to be summed and then build a logic tree to do a 4x 1bit adder.
v1 = In;
v2 = In<<3;
v3 = In<<6;
v4 = In<<9;
a1 = v1 ^ v2;
a2 = v1 & v2;
b1 = v3 ^ v4;
b2 = v3 & v4;
c2 = a1 & b1;
d2 = a2 ^ b2;
o1 = a1 ^ b1;
o2 = c2 ^ d2;
o4 = a2 & b2;
This does end up with the bits of the result spread across 3 different ints but oh well.
edit: as it happens I need the histogram of the sums so doing a bit-count of o4, o2&o1, o2 and o1 gives me what I want.
a second solution uses a perfect hash function
arr = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];
for(int i = 0; i < N; i++)
{
out[i] = arr[(In & 0b1001001001) % 30];
In >>= 1;
}
This works by noting that the 4 selected bits can only take on 16 patterns and that (by guess and check) they can be hashed into 0-15 using mod 30. From there, a table of computed values gives the needed sum. As it happens only 3 of the 4 strides I need work this way.
p.s.
Correct trumps fast. Fast trumps clear. I expect to be running this millions of time.
Maybe I am crazy, but I am having fun :D
This solution is based upon the usage of data parallelism and faking a vector cpu without actually using SSE intrinsics or anything similar.
unsigned short out[64];
const unsigned long long mask = 0x0249024902490249ul;
const unsigned long long shiftmask = 0x0001000100010001ul;
unsigned long long t = (unsigned short)(in >> 38) | (unsigned long long)(unsigned short)(in >> 39) > 40) > 41) << 48;
t &= mask;
*((unsigned long long*)(out + 38)) = (t & shiftmask) + (t >> 3 & shiftmask) + (t >> 6 & shiftmask) + (t >> 9 & shiftmask);
[... snipsnap ...]
t = (unsigned short)(in >> 2) | (unsigned long long)(unsigned short)(in >> 3) > 4) > 5) << 48;
t &= mask;
*((unsigned long long*)(out + 2)) = (t & shiftmask) + (t >> 3 & shiftmask) + (t >> 6 & shiftmask) + (t >> 9 & shiftmask);
t = (unsigned short)in | (unsigned long long)(unsigned short)(in >> 1) << 16;
t &= mask;
*((unsigned int*)out) = (unsigned int)((t & shiftmask) + (t >> 3 & shiftmask) + (t >> 6 & shiftmask) + (t >> 9 & shiftmask));
By reordering the computations, we can further reduce the execution time significantly, since it drastically reduces the amount of times that something is loaded into the QWORD. A few other optimizations are quite obvious and rather minor, but sum up to another interesting speedup.
unsigned short out[64];
const unsigned long long Xmask = 0x249024902490249ull;
const unsigned long long Ymask = 0x7000700070007u;
unsigned long long x = (in >> 14 & 0xFFFFu) | (in >> 20 & 0xFFFFu) > 26 & 0xFFFFu) > 32) << 48;
unsigned long long y;
y = x & Xmask;
y += y >> 6;
y += y >> 3;
y &= Ymask;
out[32] = (unsigned short)(y >> 48);
out[26] = (unsigned short)(y >> 32);
out[20] = (unsigned short)(y >> 16);
out[14] = (unsigned short)(y );
x >>= 1;
y = x & Xmask;
y += y >> 6;
y += y >> 3;
y &= Ymask;
out[33] = (unsigned short)(y >> 48);
out[27] = (unsigned short)(y >> 32);
out[21] = (unsigned short)(y >> 16);
out[15] = (unsigned short)(y );
[snisnap]
x >>= 1;
y = x & Xmask;
y += y >> 6;
y += y >> 3;
y &= Ymask;
out[37] = (unsigned short)(y >> 48);
out[31] = (unsigned short)(y >> 32);
out[25] = (unsigned short)(y >> 16);
out[19] = (unsigned short)(y );
x >>= 1;
x &= 0xFFFF000000000000ul;
x |= (in & 0xFFFFu) | (in >> 5 & 0xFFFFu) > 10 & 0xFFFFu) << 32;
y = x & Xmask;
y += y >> 6;
y += y >> 3;
y &= Ymask;
out[38] = (unsigned short)(y >> 48);
out[10] = (unsigned short)(y >> 32);
out[ 5] = (unsigned short)(y >> 16);
out[ 0] = (unsigned short)(y );
[snipsnap]
x >>= 1;
y = x & Xmask;
y += y >> 6;
y += y >> 3;
y &= Ymask;
out[ 9] = (unsigned short)(y >> 16);
out[ 4] = (unsigned short)(y );
Running times for 50 million executions in native c++ (all ouputs verified to match ^^) compiled as a 64 bit binary on my pc:
Array based solution: ~5700 ms
Naive hardcoded solution: ~4200 ms
The first solution: ~2400 ms
The second solution: ~1600 ms
A suggestion that I don't want to code right now is to use a loop, an array to hold partial results, and constants to pick up the bits m at a time.
loop
s[3*i] += x & (1 << 0);
s[3*i+1] += x & (1 << 1);
s[3*i+2] += x & (1 << 2);
x >> 3;
This will pick too many bits in each sum. But you can also keep track of the intermediate results and subtract from the sums as you go, to account for the bit that may not be there anymore.
loop
s[3*i] += p[3*i] = x & (1 << 0);
s[3*i+1] += p[3*i+1] = x & (1 << 1);
s[3*i+2] += p[3*i+2] = x & (1 << 2);
s[3*i] -= p[3*i-10];
s[3*i+1] -= p[3*i-9];
s[3*i+2] -= p[3*i-8];
x >> 3;
with the appropriate bounds checking, of course.
The fastest approach is to just hardcode the sums themselves.
s[0] = (x & (1<<0)) + (x & (1<<3)) + (x & (1<<6)) + (x & (1<<9));
etc. (The shifts occur at compile time.)