What optimization is making my rust program so much faster? - rust

Frustrated that I could not solve a Sudoku puzzle, I quickly hacked together a simple recursive backtracking solver:
fn is_allowed(board: &[[u8; 9]; 9], row: usize, col: usize, x: u8) -> bool {
for i in 0..9 {
if board[row][i] == x {
return false;
}
if board[i][col] == x {
return false;
}
}
let r = row - (row % 3);
let c = col - (col % 3);
for i in r..(r + 3) {
for j in c..(c + 3) {
if board[i][j] == x {
return false;
}
}
}
true
}
fn solve(board: &mut [[u8; 9]; 9]) -> bool {
for i in 0..9 {
for j in 0..9 {
if board[i][j] == 0 {
for x in 1..=9 {
if is_allowed(board, i, j, x) {
board[i][j] = x;
if solve(board) {
return true
}
board[i][j] = 0;
}
}
return false;
}
}
}
true
}
fn main() {
let mut board = [
[ 0, 0, 8, 0, 0, 4, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 7 ],
[ 0, 0, 6, 0, 0, 0, 0, 1, 0 ],
[ 0, 0, 0, 0, 0, 0, 5, 0, 9 ],
[ 0, 0, 0, 6, 0, 0, 0, 0, 0 ],
[ 0, 2, 0, 8, 1, 0, 0, 0, 0 ],
[ 9, 4, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 1, 8, 0 ],
[ 0, 0, 7, 0, 0, 5, 0, 0, 0 ],
];
if solve(&mut board) {
for i in 0..9 {
println!("{:?}", board[i]);
}
} else {
println!("no solution");
}
}
When running without optimizations (cargo run), it takes more than 6 minutes to run.
When running with optimizations (cargo run --release), it takes about 7 seconds to run.
What optimization is leading to such a difference?

It is difficult to be sure without analyzing the generated assembly, but I think that it is related to the combination of these optimizations:
Loop unrolling: the compiler knows that each loop runs 8 times, so instead of a loop it compiles the loop body 8 times with the index as a constant. This is why the godbold link by #MatthieuM in the comments above is so long.
Range checking: since i, j and k are now constants (in the unrolled loops) and the arrays are of known size, the compiler will omit all range checks.
Function inlining.
In fact, each time you write board[i][j]:
In debug mode, you are calling two library functions that do checkings and computations.
In release mode each instance of such code is just a read or write to fixed offset in the stack.

Related

Project plane on a specific distance using Three.js

I have a rectangle defined by 4 points. I want to move it to the left or right by specific distance. By moving I mean that result rectangle should be parallel to the original and if we put straights through corresponding points we will get rectangular cuboid.
On an image I am given coordinates of points A,B,C,D and distance H.
How can I calculate 4 new points using Three.js?
I guess it has something to do with projection, but I couldn't find an easy way to do it.
Just an example. Aqua lines are base, yellow lines are shifted ones:
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three#0.136.0/examples/jsm/controls/OrbitControls";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 5, 5);
let renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
let controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.enablePan = false;
scene.add(new THREE.GridHelper());
let dir = new THREE.Vector3(0, 0, 1);
let colors = [];
let ptsBase = [
[-1, 1], [1, 1], [1, -1], [-1, -1]
].map(p => {
colors.push(0, 1, 1);
return new THREE.Vector3(p[0], p[1], 0);
});
let ptsShift = ptsBase.map(p => {
colors.push(1, 1, 0);
return p.clone().addScaledVector(dir, 2)
});
let ptsFinal = ptsBase.concat(ptsShift);
let g = new THREE.BufferGeometry().setFromPoints(ptsFinal);
g.setIndex([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]);
g.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
let m = new THREE.LineBasicMaterial({vertexColors: true});
let l = new THREE.LineSegments(g, m);
scene.add(l);
renderer.setAnimationLoop(() => {
controls.update();
renderer.render(scene, camera);
});
</script>
What I found to be working is getting normal vector, multiplying it by distance, and adding it to my point vectors.
I did it like this
let pointA = new THREE.Vector3(0, 0, 0);
let pointB = new THREE.Vector3(1, 0, 0);
let pointC = new THREE.Vector3(1, 1, 0);
let pointD = new THREE.Vector3(0, 1, 0);
const distance = 0.5;
let triangle = new THREE.Triangle(pointA, pointB, pointC);
let plane = new THREE.Plane();
triangle.getPlane(plane);
let normalVector = plane.normal.multiplyScalar(distance);
pointA1 = pointA.clone().add(normalVector);
pointB1 = pointB.clone().add(normalVector);
pointC1 = pointC.clone().add(normalVector);
pointD1 = pointD.clone().add(normalVector);

How to mirror front camera [duplicate]

Can I horizontally flip/reflect a shape item in QML. For example; I have the below shape:
Can I flip/reflect it horizontally to produce:
I know I could edit my QML code to draw the lines differently but it would be much simpler to just use a QML animation or something to flip it if thats possible.
Shape {
id: annotationHLine;
anchors.left: annotationShp.right;
anchors.top: annotationShp.top;
anchors.topMargin: annotationShp.height * 0.5;
ShapePath {
strokeWidth: 2;
strokeColor: "Green";
fillColor: "transparent";
startX: -slant; startY: 0;
PathLine { x: relativeTargetX*0.5; y: 0 }
PathLine { x: relativeTargetX; y: relativeTargetY }
}
}
you can use transform and Scale
transform: Scale{ xScale: -1 }
Yes you can, by simply setting a horizontal mirror transformation matrix to the shape:
transform: Matrix4x4 {
matrix: Qt.matrix4x4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
}
Edit:
The x position doesn't really change, it is still the same, it is just that the object is now rendered with the transformation. You can compensate for that by stacking a translate on top of the matrix:
transform: [
Matrix4x4 {
matrix: Qt.matrix4x4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
},
Translate {
x: annotationHLine.width
}
]
Edit 2:
Actually, you can incorporate the translation in the original matrix to simplify things a bit:
transform: Matrix4x4 {
matrix: Qt.matrix4x4( -1, 0, 0, but.width, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)}
}

Why array registers only the last object multiple times Nodejs

Im trying to fill an array with n objects but it just register the last object n times this is my code :
async function show(carId,debut,fin){
let score = {}
let array = [];
res = await ScoreData(carId);
for(i = 0; i < res.entries.length ; i++){
date = res.entries[i].Timestamp._.toISOString().slice(0, 10);
if (date >= debut && date <= fin){
score.roadSpeed_1 = (res.entries[i].speed_1._)/((res.entries[i].speed_1._)+ (res.entries[i].speed_2._) + (res.entries[i].speed_3._))*10000;
score.roadSpeed_2 = (res.entries[i].speed_2._)/((res.entries[i].speed_1._)+ (res.entries[i].speed_2._) + (res.entries[i].speed_3._))*10000;
score.roadSpeed_3 = (res.entries[i].speed_3._)/((res.entries[i].speed_1._)+ (res.entries[i].speed_2._) + (res.entries[i].speed_3._))*10000;
score.Acceleration = Math.round(res.entries[i].millage._ / res.entries[i].Vehicle_speed._)
console.log(res.entries[i].millage._ / res.entries[i].Vehicle_speed._)
array.push(score);
}
}
console.log(array)
}
This is the result :
[
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 },
{ roadSpeed_1: 100, roadSpeed_2: 0, roadSpeed_3: 0, Acceleration: 4 }
]
Objects in JavaScript are passed by reference. When more than one variable is set to store either an object , array or function , those variables will point to the same allocated space in the memory. Passed by reference. Source : Link
Better solution i guess :
array.push({roadspeed_1: operation 1, roadspeed_2: operation 2 ,roadspeed_3: operation 3 });

How do I draw a pixmap to root window with xcb?

I'm trying to write a window manager with a wallpaper switcher:
void smoke_change_background(smoke_wm_state_t *config, char *desktop) {
struct smoke_desktop_list_element_t *node = smoke_desktop_list_node(config->tree, desktop);
if (node->background != 0) {
xcb_intern_atom_reply_t *xpmap = xcb_intern_atom_reply(config->connection,
xcb_intern_atom(config->connection,
false,
strlen("_X_ROOTPMAP_ID"),
"_X_ROOTPMAP_ID"),
NULL);
xcb_intern_atom_reply_t *esetr = xcb_intern_atom_reply(config->connection,
xcb_intern_atom(config->connection,
false,
strlen("ESETROOT_PMAP_ID"),
"ESETROOT_PMAP_ID"),
NULL);
xcb_get_property_reply_t *xrepl = xcb_get_property_reply(config->connection,
xcb_get_property(config->connection,
0,
config->screen->root,
xpmap->atom,
XCB_ATOM_PIXMAP,
0,
32),
NULL);
uint32_t *xp = (uint32_t*) xcb_get_property_value(xrepl);
xcb_get_property_reply_t *erepl = xcb_get_property_reply(config->connection,
xcb_get_property(config->connection,
0,
config->screen->root,
esetr->atom,
XCB_ATOM_PIXMAP,
0, 32),
NULL);
uint32_t *ep = (uint32_t*) xcb_get_property_value(erepl);
xcb_change_property(config->connection,
XCB_PROP_MODE_REPLACE,
config->screen->root,
xpmap->atom,
XCB_ATOM_PIXMAP,
32, 1,
(void*) &node->background);
xcb_change_property(config->connection,
XCB_PROP_MODE_REPLACE,
config->screen->root,
esetr->atom,
XCB_ATOM_PIXMAP,
32, 1,
(void*) &node->background);
xcb_free_pixmap(config->connection, *xp);
xcb_free_pixmap(config->connection, *ep);
uint32_t values[1];
values[0] = node->background;
xcb_change_window_attributes(config->connection, config->screen->root, XCB_CW_BACK_PIXMAP, values);
xcb_clear_area(config->connection, false, config->screen->root, 0, 0, 0, 0);
xcb_flush(config->connection);
}
}
This code should change the root's pixmap and it should be displayed in my Xephyr window, but it is not. What's wrong?

react - setState find object item then assign

i have object in state -
this.state = {
states: {
na: 0, s1a: 0, s2a: 0, s3a: 0, s4a: 0, l1a: 0, l2a: 0, l3a: 0, t1a: 0, t2a: 0, t3a: 0,
nb: 0, s1b: 0, s2b: 0, s3b: 0, s4b: 0, l1b: 0, l2b: 0, l3b: 0, t1b: 0, t2b: 0, t3b: 0
},
and i want to change value of some key i my function -
onInputUpdated(id){
var array = {};
let char = id.slice(-1);
switch(char){
case 'a':
array[id] = this.getY(ReactDOM.findDOMNode(this.refs[id].refs.inp).value);
break;
case 'b':
array[id] = this.getX(ReactDOM.findDOMNode(this.refs[id].refs.inp).value);
break;
}
this.setState({
states: { id : array[id]}
});
but there is no id, id represents string 'na' or others... so how i can do it? any tips pls? btw onIputUpdated(id) is callBack from children..
Firstly, you cant update nested states directly. You will to have to update the whole "states" object. Something like this
let oldStates = this.state.states;
oldStates[id] = array[id];
this.setState({
states: {
...oldStates
}
});

Resources