How can this formula to swizzle rows be simplified? - algorithm

The problem is quite simple to understand but solving it was not as easy as it sounded at first.
Let's assume the following, an image that is 8*4, normal order is easy, you return the pixel index:
// 00 01 02 03 04 05 06 07
// 08 09 10 11 12 13 14 15
// 16 17 18 19 20 21 22 23
// 24 25 26 27 28 29 30 31
Now suppose you want to swizzle rows like so:
// 00 01 02 03 04 05 06 07
// 16 17 18 19 20 21 22 23
// 08 09 10 11 12 13 14 15
// 24 25 26 27 28 29 30 31
I solved it, not without trouble to be honest, with the following formula:
index / 8 % 2 * 16 + index / 16 * 8 + index % 8
Isn't there a simpler formula to get the same result?

Assuming / and % return the quotient and remainder in the Euclidean division:
The classic ordering can be obtained as:
row = n / 8
col = n % 8
And the swizzled ordering can be obtained as:
col = n % 8
old_row = n / 8
new_row = 2 * (old_row / 2) + (1 - (old_row % 2))
Explanation:
2 * (old_row / 2) groups the rows two by two;
(1 - (old_row % 2)) swaps row 0 and row 1 of each group.

Related

Nested for/while loop python triangle

Code
num = int(input(“Enter the number of lines: “))
for i in range(10):
for j in range(1,i):
print(num, the end='')
num = num+1
print()
I am writing a program which is should be like this.
Enter the number of lines: 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37
38 39 40 41 42 43 44
45 46 47 48 49 50
51 52 53 54 55
56 57 58 59
60 61 62
63 64
65
I don’t have any example from the lecturer, i just following the step from website, but the output of my code is like this: i am confused where i made the mistake, don’t get any clue to wear for or while. Please help me, thank you.
10
11 12
13 14 15
16 17 18 19
20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36 37
38 39 40 41 42 43 44 45
Try this:
input_data = input('Enter number of lines: ')
num = int(input_data)
# how many items to print in the first line?
items_to_print = num
# what's the starting number?
print_number = 11
for i in range(0, num):
# don't decrease num
# decrease items_to_print
# each line will reduce 1 item to print
for j in range(0, items_to_print):
print(print_number, end = ' ')
print_number += 1
print()
items_to_print -= 1
Result:
Enter number of lines: 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37
38 39 40 41 42 43 44
45 46 47 48 49 50
51 52 53 54 55
56 57 58 59
60 61 62
63 64
65
Explanation
Start small and make your way up.
First just do this:
input_data = input('Enter number of lines: ')
num = int(input_data)
print(num)
That'll print 10 if you entered 10. Great.
Second, add the first for loop and test whether it will print 10 rows.
input_data = input('Enter number of lines: ')
num = int(input_data)
for i in range(0, num):
print(f'Printing line {i}')
Third, try to print a block of 10 x 10. So, you add another variable called items_to_print. Set it to num. If you enter 10 as input, you will get 10 rows and 10 columns.
input_data = input('Enter number of lines: ')
num = int(input_data)
print_number = 0
items_to_print = num
for i in range(0, num):
print(f'Printing line {i}')
for j in range(0, items_to_print):
print(print_number, end = ' ')
Fourth step is to reduce the number of zeros printed before restarting the i loop. So, you decrement items_to_print.
input_data = input('Enter number of lines: ')
num = int(input_data)
print_number = 0
items_to_print = num
for i in range(0, num):
print(f'Printing line {i}')
for j in range(0, items_to_print):
print(print_number, end = ' ')
items_to_print -= 1
Now that your printing is working great, let's set print_number to start with 11 and each time a print happens in j loop, increment print_number. Then you will have same code I published at the top of this answer.
Well you have three little problems so let's address them one at a time.
First: default range function starts at 0 so when your j starts at one you are missing one iteration of the cicle. That explains missing one column and row but not two so let's keep going.
Second: the range function is non inclusive meaning you're I goes from 0 to 9 then in the inner loop you go from 1 to a maximum of 8. There's your missing second iteration.
Third: you are looping from 1 to an encreasing value what you want is the opposite so you need a decreasing range.
This is how you're code should look like.
num = 11
for i in range(10, 0, - 1):
for j in range(i):
print(num, end = " ")
num += 1
print()
Good luck and happy coding

Error returning when counting records in a query grouped in Oracle

I have a problem trying to group some records and trying to count the number of records returned by a query is adding an example:
07 COMERCIO 92
15 SERVICIOS OTROS 41
01 AGRICULTURA, GANADERIA Y SILVICULTURA 141
04 INDUSTRIA MANUFACTURERA 28
10 BANCA Y FINANZAS 5
12 ADMINISTRACION PUBLICA 16
03 MINERIA 3
16 HOGAR 2
08 HOTELES Y RESTAURANTES 37
11 EMPRESARIAL 21
14 SOCIAL Y SALUD 4
06 CONSTRUCCIÓN 3
09 TRANSPORTE 30
13 EDUCACION 10
This is query:
SELECT
AGRUP.VC_CODDET AS CHR_SECECO,
AGRUP.VC_NOMDET AS VC_SECECO,
0 AS INT_NROPRESTAMO,
COUNT(*) INTO_BENEFICIARIOS,
0 AS DEC_SALCON
FROM TB_JSI_PRESTAMO_DETALLE PREDET
INNER JOIN TB_JSI_PRESTAMO PRE ON
PRE.INT_IDPRESTAMO=PREDET.INT_IDPRESTAMO
INNER JOIN TB_JSI_BENEFICIARIO_IFI BENIFI ON
BENIFI.INT_IDBENEIFI=PRE.INT_IDBENEIFI
INNER JOIN TB_JSI_OPERACION OPE ON PRE.INT_IDOPE = OPE.INT_IDOPE AND
TRUNC(TO_DATE(OPE.DT_FECVEN))>TRUNC(TO_DATE('30/09/2018', 'DD/MM/YY'))
INNER JOIN TB_JSI_CIIU CIIU ON PRE.INT_IDACT = CIIU.INT_IDACT AND
PRE.INT_IDSEC=CIIU.INT_IDCLAS
INNER JOIN TB_JSI_TABLA_DET SECECO ON SECECO.INT_IDDET=CIIU.INT_IDCLAS
INNER JOIN TB_JSI_AGRUPA_SECTOR AGRSEC ON SECECO.INT_IDDET =
AGRSEC.INT_IDSEC
INNER JOIN TB_JSI_TABLA_DET AGRUP ON AGRSEC.INT_IDAGRU = AGRUP.INT_IDDET
INNER JOIN TB_JSI_TABLA_DET MON ON OPE.INT_IDMON = MON.INT_IDDET
INNER JOIN TB_JSI_IFI IFI ON OPE.INT_IDIFI = IFI.INT_IDIFI
WHERE TRUNC(PREDET.DTE_FECPRO) = (
SELECT
TRUNC(DTE_FECPRO)
FROM (SELECT
DTE_FECPRO
FROM TB_JSI_PRESTAMO_DETALLE
WHERE DTE_FECPRO<=TO_DATE('30/09/2018','DD/MM/YY')
AND DEC_SALDOL>0
ORDER BY DTE_FECPRO DESC)
WHERE ROWNUM = 1
)
AND (NULL IS NULL OR OPE.INT_IDTIPPRO =2)
AND (NULL IS NULL OR OPE.INT_IDMON = 364)
AND (NULL IS NULL OR OPE.INT_IDIFI=72)
GROUP BY AGRUP.VC_CODDET, AGRUP.VC_NOMDET
and should return this result
07 COMERCIO 92
15 SERVICIOS OTROS 41
01 AGRICULTURA, GANADERIA Y SILVICULTURA 141
04 INDUSTRIA MANUFACTURERA 28
10 BANCA Y FINANZAS 4
12 ADMINISTRACION PUBLICA 16
03 MINERIA 3
16 HOGAR 2
08 HOTELES Y RESTAURANTES 37
11 EMPRESARIAL 21
14 SOCIAL Y SALUD 4
06 CONSTRUCCIÓN 3
09 TRANSPORTE 30
13 EDUCACION 10
since I have these records and when counting I should return 4 and not 5
269516 10 BANCA Y FINANZAS 1
269558 10 BANCA Y FINANZAS 1
269592 10 BANCA Y FINANZAS 2
269611 10 BANCA Y FINANZAS 1
#Roller, I have analyzed the result and it is now clear that one of the tables used in the query has two records with the matching condition and that is why it is returning 5 and not 4.
You just need to identify the table and if you are not able to, then use the following trick.
First of all, identify the table, basis of which you are saying that there must be 4 rows and then use that table's PK in the count with distinct as follows:
COUNT(DISTINCT MY_PK)

How to rotate a centered hexagonal bitboard?

Consider the following centered hexagonal bitboard representation (padding is in boldface):
56
55 49
54 48 42
53 47 41 35
52 46 40 34 28
45 39 33 27
44 38 32 26 20
37 31 25 19
36 30 24 18 12
29 23 17 11
28 22 16 10 04
21 15 09 03
20 14 08 02 60
13 07 01 59
06 00 58
63 57
56
This representation fits in a 64-bit integer and allows for easy movement in the 6 hexagonal directions by rotating bits 1, 7 or 8 spaces to the right or to the left respectively. If it helps with visualization, you can deform this hexagon into a square:
42 43 44 45 46 47 48
35 36 37 38 39 40 41
28 29 30 31 32 33 34
21 22 23 24 25 26 27
14 15 16 17 18 19 20
07 08 09 10 11 12 13
00 01 02 03 04 05 06
Now, what I want to do is rotate this bitboard 60° clockwise, such that the [45,46,47,38,39,31] triangle becomes the [48,41,34,40,33,32] triangle, etc. How do I do this?
This permutation is kind of a mess, with every relevant bit having a distinct move-distance. The permutation diagram looks like this (top row is output):
That does suggest some approaches though. If we look near the top, every "group" is formed by gathering some bits from the input in ascending order, so it can be done with 7 compress_right operations aka PEXT which is efficient on Intel (not so efficient on AMD so far). What that really comes down to is sampling the vertical columns, so extracting bits with a stride of 8.
So if PEXT is acceptable, it could be done like this (not tested):
uint64_t g0 = _pext_u64(in, 0x8080808);
uint64_t g1 = _pext_u64(in, 0x404040404);
uint64_t g2 = _pext_u64(in, 0x20202020202);
uint64_t g3 = _pext_u64(in, 0x1010101010101);
uint64_t g4 = _pext_u64(in, 0x808080808080);
uint64_t g5 = _pext_u64(in, 0x404040404000);
uint64_t g6 = _pext_u64(in, 0x202020200000);
uint64_t out = g0 | (g1 << 7) | (g2 << 14) | (g3 << 21) |
(g4 << 28) | (g5 << 35) | (g6 << 42);
This permutation is not routable by a butterfly network, but Beneš networks are universal so that will work.
So it can be done with 11 of these permute steps, also known as delta swaps:
word bit_permute_step(word source, word mask, int shift) {
word t;
t = ((source >> shift) ^ source) & mask;
return (source ^ t) ^ (t << shift);
}
There is some choice in how to create the exact masks, but this works:
x = bit_permute_step(x, 0x1001400550054005, 1);
x = bit_permute_step(x, 0x2213223111023221, 2);
x = bit_permute_step(x, 0x01010B020104090E, 4);
x = bit_permute_step(x, 0x002900C400A7007B, 8);
x = bit_permute_step(x, 0x00000A0400002691, 16);
x = bit_permute_step(x, 0x0000000040203CAD, 32);
x = bit_permute_step(x, 0x0000530800001CE0, 16);
x = bit_permute_step(x, 0x000C001400250009, 8);
x = bit_permute_step(x, 0x0C00010403080104, 4);
x = bit_permute_step(x, 0x2012000011100100, 2);
x = bit_permute_step(x, 0x0141040000000010, 1);

The Traveling Salesman algorithm bug

I have tried to make an algorithm solving the traveling salesman problem as follows:
%main function:
[siz, ~] = size(table);
done(1:siz) = false;
done(1) = true;
[dist, path] = bruteForce(table, done, 1);
function bruteForce:
function [distance, path] = bruteForce(table, done, index)
size = length(done);
dmin = inf;
distance = 0;
path = [];
%finding minimum distance
for i = 1:size
if ~done(i)
done(i) = true;
%iterating through all nodes using recursion
[d, p] = bruteForce(table, done, i);
if (d < dmin)
dmin = d;
path = [i p];
distance = dmin + table(i, index);
end
%freing the node again
done(i) = false;
end
end
if distance == 0
distance = table(1, index);
path = 1;
end
Unfortunately, for the following matrix:
B = [0 29 20 21 16 31 100 12 4 31 18;
29 0 15 29 28 40 72 21 29 41 12;
20 15 0 15 14 25 81 9 23 27 13;
21 29 15 0 4 12 92 12 25 13 25;
16 28 14 4 0 16 94 9 20 16 22;
31 40 25 12 16 0 95 24 36 3 37;
100 72 81 92 94 95 0 90 101 99 84;
12 21 9 12 9 24 90 0 15 25 13;
4 29 23 25 20 36 101 15 0 35 18;
31 41 27 13 16 3 99 25 35 0 38;
18 12 13 25 22 37 84 13 18 38 0];
Instead of getting the expected result:
1-8-5-4-10-6-3-7-2-11-9-1 = 253km
I get:
1-8-11-3-4-6-10-5-9-2-7-1 = 271km
Could you help me find the bug?
If brute force is a must and speed is no issue, then just use the perms function for the number of cities. This allows for an easy implementation:
table = [0 29 20 21 16 31 100 12 4 31 18;
29 0 15 29 28 40 72 21 29 41 12;
20 15 0 15 14 25 81 9 23 27 13;
21 29 15 0 4 12 92 12 25 13 25;
16 28 14 4 0 16 94 9 20 16 22;
31 40 25 12 16 0 95 24 36 3 37;
100 72 81 92 94 95 0 90 101 99 84;
12 21 9 12 9 24 90 0 15 25 13;
4 29 23 25 20 36 101 15 0 35 18;
31 41 27 13 16 3 99 25 35 0 38;
18 12 13 25 22 37 84 13 18 38 0];
[siz, ~] = size(table);
[bp, b] = bruteForce(table, siz)
function [bestpath, best] = bruteForce(table, siz)
p = perms(1:siz);
[r, c] = size(p);
best = inf;
for i = 1:r
path = p(i, :);
dist = distCalculatorReturn(table, path);
if dist < best
best = dist;
bestpath = path;
end
end
bestpath = [bestpath, bestpath(1)];
end
function [totaldist] = distCalculatorReturn(distMatrix, proposedPath)
dist = 0;
i = 1;
while i ~= length(proposedPath)
dist = dist + distMatrix(proposedPath(i),proposedPath(i+1));
i = i+1;
end
dist = dist + distMatrix(proposedPath(1), proposedPath(end));
totaldist = dist;
end
This yields the answer you are looking for. However, if you are only solving problems of that size, why not apply a standard simulated annealing. This gives much faster solution times and should solve the problem size consistently:
table = [0 29 20 21 16 31 100 12 4 31 18;
29 0 15 29 28 40 72 21 29 41 12;
20 15 0 15 14 25 81 9 23 27 13;
21 29 15 0 4 12 92 12 25 13 25;
16 28 14 4 0 16 94 9 20 16 22;
31 40 25 12 16 0 95 24 36 3 37;
100 72 81 92 94 95 0 90 101 99 84;
12 21 9 12 9 24 90 0 15 25 13;
4 29 23 25 20 36 101 15 0 35 18;
31 41 27 13 16 3 99 25 35 0 38;
18 12 13 25 22 37 84 13 18 38 0];
[path, dist] = tsp(table, length(table))
function [path, dist] = tsp(D, n)
L = 40*n;
epsi = 1e-9;
x = randperm(n);
fx = distCalculatorReturn(D, x);
T = 1000000;
while T > epsi
for i=1:L
num1 = 1 + floor(rand*n);
num2 = 1 + floor(rand*n);
while num1 == num2
num1 = 1 + floor(rand*n);
end
y = x;
swap1 = y(num1);
y(num1) = y(num2);
y(num2) = swap1;
fy = distCalculatorReturn(D,y);
if fy < fx
x = y;
fx = fy;
elseif rand < exp(-(fy - fx)/T)
x = y;
fx = fy;
end
end
T = 0.9*T;
end
path = [x, x(1)];
dist = fx;
end
Your code does not compute the distance for each possible path (as bruteForce suggests). Instead it always starts at node 1 and from there goes always to the node that is closest to the current node. As your example shows, that does not necessarily lead to the overall shortest path. You will need to go through all possible paths to be sure you find the optimum.
Here is my go at your problem:
% distance matrix
B = [0 29 20 21 16 31 100 12 4 31 18;
29 0 15 29 28 40 72 21 29 41 12;
20 15 0 15 14 25 81 9 23 27 13;
21 29 15 0 4 12 92 12 25 13 25;
16 28 14 4 0 16 94 9 20 16 22;
31 40 25 12 16 0 95 24 36 3 37;
100 72 81 92 94 95 0 90 101 99 84;
12 21 9 12 9 24 90 0 15 25 13;
4 29 23 25 20 36 101 15 0 35 18;
31 41 27 13 16 3 99 25 35 0 38;
18 12 13 25 22 37 84 13 18 38 0];
% compute all possible paths assuming we always start at node 1
nNodes = size(B,1);
paths = perms(2:nNodes);
nPaths = size(paths,1);
paths = [ones(nPaths,1) paths ones(nPaths,1)]; % start and finish tour at node 1
% with a random start point:
% paths = perms(1:nNodes);
% paths = [perms(1:nNodes) paths(:,1)];
% compute overall distance for each path
distance = inf;
for idx=1:nPaths
from = paths(idx,1:end-1);
to = paths(idx,2:end);
d = sum(diag(B(from,to)));
if d<distance
distance = d;
optPath = paths(idx,:);
end
end
This leads to the following result:
optPath = [1 9 11 2 7 3 6 10 4 5 8 1]
distance = 253

Person age program in pascal

I have this task and i can't figure out how to do it.
I need to find persons age in days, there are given birth and death dates, there's data file:
8
Albertas Einšteinas 1879 03 14 1955 04 18
Balys Sruoga 1896 02 02 1947 10 16
Antanas Vienuolis 1882 04 07 1957 08 17
Ernestas Rezerfordas 1871 08 30 1937 10 17
Nilsas Boras 1885 10 07 1962 11 18
Nežiniukas Pirmasis 8 05 24 8 05 25
Nežiniukas Antrasis 888 05 25 888 05 25
Nežiniukas Trečiasis 1 01 01 125 01 01
and there's how result file should look like:
1879 3 14 1955 4 18 27775
1896 2 2 1947 10 16 18871
1882 4 7 1957 8 17 27507
1871 8 30 1937 10 17 24138
1885 10 7 1962 11 18 28147
8 5 24 8 5 25 1
888 5 25 888 5 25 0
1 1 1 125 1 1 45260
Few things to notice: all februarys have 28 days.
My function for calculating age:
function AmziusFunc(Mas : TZmogus) : longint;
var amzius, max : longint;
begin
max := 125 * 365;
amzius := (Mas.mirY - Mas.gimY) * 365 + (Mas.mirM - Mas.gimM) * 31 +
(Mas.mirD - Mas.gimD);
if ( amzius >= max ) then amzius := 0;
AmziusFunc := amzius;
end;
What should i change there? Thanks.
function AmziusFunc(Mas : TZmogus) : longint;
var amzius, max : longint;
begin
max := 125 * 365;
amzius := (Mas.mirY - Mas.gimY) * 365 + (Mas.mirM - Mas.gimM) * 31 +
(Mas.mirD - Mas.gimD);
if ( amzius >= max ) then amzius := 0;
AmziusFunc := amzius;
end;

Resources