In Dart, is there a simple way to check whether the sum of a list will produce a 'real' value (a value that doesn't overflow or underflow)?
Examples:
overflowSafeSum([0,1,2]) //3
overflowSafeSum([1,9223372036854775807]) //Over
overflowSafeSum([-1,-9223372036854775808]) //Under
I'm new to dart, this is the best I got right now:
import 'dart:math' show pow;
enum Overflow {
over,
under,
}
void main() {
//idea: Iterate through the elements of a list and add them,
//each time the sum overflows: increase overflowCounter by 1
//each time the sum underflows: decrease overflowCounter by 1
//if all the elements have been added and the overflowCounter == 0, the sum must be real
overflowSafeSum(List<int> userList) {
var sum = 0, overflowCounter = 0;
for (int index = 0, nextTerm;
index < userList.length;
index++, sum += nextTerm) {
nextTerm = userList[index];
if (sum.sign != nextTerm.sign) {
continue; //adding a postive and negative can't overflow or underflow
} else if (sum >= 0 && nextTerm >= 0) {
if ((sum + nextTerm) < 0) overflowCounter++;
} else {
if ((sum + nextTerm) >= 0) overflowCounter--;
}
}
if (overflowCounter == 0) {
return sum;
} else if (overflowCounter > 0) {
return Overflow.over;
} else {
return Overflow.under;
}
}
var myList = [1,0,(pow(2,63)-1).toInt()];
print(overflowSafeSum(myList)); //Overflow.over
}
(To be pedantic: "underflow" is not negative overflow. Overflow occurs when the magnitude of a number is too large to be represented, regardless of sign. Underflow is an issue with floating-point operations where the magnitude of a number is too small (too close to 0) to be represented.)
You can't generally detect overflow with Dart ints since Dart for the web is transpiled to JavaScript, where ints are backed by JavaScript numbers (IEEE-754 double-precision floating-point values). If you instead use Int32 or Int64 from package:fixnum (or if you restrict yourself to the Dart VM), then you could make a helper function like:
class OverflowException implements Exception {
OverflowException({this.positive = true});
bool positive;
}
Int64 checkedAdd(Int64 a, Int64 b) {
var sum = a + b;
if (a > 0 && b > 0 && sum < 0) {
throw OverflowException(positive: true);
}
if (a < 0 && b < 0 && sum > 0) {
throw OverflowException(positive: false);
}
return sum;
}
From there, you could trivially add a function that calls it in a loop:
Int64 overflowSafeSum(Iterable<int> numbers) {
var sum = Int64(0);
for (var number in numbers) {
sum = checkedAdd(sum, Int32(number));
}
return sum;
}
or if you prefer using Iterable.fold:
Int64 overflowSafeSum(Iterable<int> numbers) =>
numbers.fold<Int64>(Int64(0), (sum, i) => checkedAdd(sum, Int64(i)));
Related
I m making a card game where 3 random numbers are generated..I need to check are these numbers Row numbers...
like 4 6 5 and 23,24,22. are row numbers
I have made method but I think there should be easy arithmetic formulas
I have tried this and working well, but I need simple arithmatic formula to avoid use of array and for
bool isAllInRow(int num1, int num2,int num3)
{
//subject : tinpati
List<int> numbers=[num1,num2,num3];
bool is_in_row=true;
numbers.sort();
if(numbers[0]==1 && numbers[1]==12 && numbers[2]==13)
return true;
for(int x=0;x<numbers.length-1;x++)
{
if(numbers[x]-numbers[x+1]!=-1)
{
is_in_row=false;
break;
}
}
return is_in_row;
}
So you want to know if the cards form a straight, with aces both low and high.
Is the "three cards" fixed, or would you want to generalize to more cards?
Sorting should be cheap for such a short list, so that's definitely a good start. Then you just need to check the resulting sequence is increasing adjacent values.
I'd do it as:
bool isStraight(List<int> cards) {
var n = cards.length;
if (n < 2) return true;
cards.sort();
var first = cards.first;
if (first == 1 && cards[1] != 2) {
// Pretend Ace is Jack if n == 3.
// Accepts if remaining cards form a straight up to the King.
first = 14 - n;
}
for (var i = 1; i < n; i++) {
if (cards[i] != first + i) return false;
}
return true;
}
This code rejects card sets that have duplicates, or do not form a straight.
I think you are looking for Arithmetic Progression.
bool checkForAP(List<int> numberArr) {
numberArr.sort();
int diff = numberArr[1] - numberArr[0];
if (numberArr[2] - numberArr[1] != diff) {
return false;
}
return true;
}
And modify your function like
bool isAllInRow(int num1, int num2,int num3) {
//subject : tinpati
List<int> numbers=[num1,num2,num3];
bool is_in_row=true;
numbers.sort();
if(numbers[0]==1 && numbers[1]==12 && numbers[2]==13)
return true;
return checkForAP(numbers);
}
Note: remove sort in AP method as it is of no use. Since your numbers
list length is 3 I directly compared numbers for AP, the same can also
be written for n numbers with for.
bool checkForAp(numberArr) {
numberArr.sort();
int diff = numberArr[1] - numberArr[0];
for(int i = 2; i< numberArr.length ;i++) {
if (numberArr[i] - numberArr[i - 1] != diff) {
return false;
}
}
return true;
}
You could do it like this:
bool isAllInRow(int num1, int num2,int num3) {
if (num1 == num2 || num2 == num3) return false;
var maxNum = max(num1, max(num2, num3));
var minNum = min(num1, min(num2, num3));
return (maxNum - minNum == 2) || (minNum == 1 && maxNum == 13 && num1 + num2 + num3 == 26);
}
I am trying to find the distance of a node from the root of a binary tree but I am getting right answer up to only 3 branches only. like for the node(4) I am getting 3 and for the node (9) and node(10) I am getting 3
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
node(int val)
{
data = val;
left = NULL;
right = NULL;
}
};
int find_node(node* root,int n)
{
static int length=1;
if (root== NULL)
{
return 0;
}
if (root->data==n)
{
return length;
}
length=length+(find_node(root->left,n)||find_node(root->right,n));
// find_node(root->left,n);
// find_node(root->right,n);
return length;
}
int main ()
{
struct node* root = new node(1);
root->left = new node(2);
root->right = new node(3);
root->left->left = new node(4);
root->left->right = new node(5);
root->right->left = new node(6);
root->right->right = new node(7);
root->right->right->right = new node(9);
root->right->right->right->right = new node(10);
cout <<find_node(root,10);
return 0;}
When your code reaches the first leaf node (with data 4), the following assignment will assign 1:
length=length+(find_node(root->left,n)||find_node(root->right,n));
Because the expression resolves to 1+(0||0), i.e. 1. And so 1 is returned.
The caller (at the node with data 2) will thus receive this 1, and so the above statement will yield 2, since it resolves to 1+(1||......), which is 2 -- the second operand of || is not evaluated.
The parent caller (at the node with data 1), will thus receive this 2. The assignment there resolves to 1+(2||.....), which is again 2 -- realise that || is a logical operator, so it can only evaluate to a boolean value (i.e. 0 or 1).
The issues
In summmary:
You should not use || as it can only evaluate to 0 or 1, losing the actual value from recursion that you need.
You should not use a static variable. For one, it would not reset if you would make a second call to this function from the main program code. Instead, every recursive call should just "mind its own business" and return the depth of n from the given root. The caller should add 1 to that if n was found.
Correction
int find_node(node* root, int n)
{
if (root == NULL)
{
return 0;
}
if (root->data == n)
{
return 1;
}
int length = find_node(root->left, n);
if (!length)
{
length = find_node(root->right, n);
}
if (!length)
{
return 0;
}
return 1 + length;
}
I need to get all possible subsets of an array.
Say I have this:
<int>[1, 2, 3]
How do I get this?
[], [1], [2], [3],[1, 2], [2, 3], [1, 3], [1, 2, 3]
I am interested in all subsets. For subsets of specific length, refer to the following questions:
How to find all subsets of a set in JavaScript?
Here is my take on it, with only native function as in your link:
List getAllSubsets(List l) => l.fold<List>([[]], (subLists, element) {
return subLists
.map((subList) => [
subList,
subList + [element]
])
.expand((element) => element)
.toList();
});
If you want a specific size:
List getSizedSubsets(List l, int size) =>
getAllSubsets(l).where((element) => element.length == size).toList();
I'd probably go with something simple like:
Iterable<Set<E>> subsets<E>(Set<E> elements) sync* {
if (elements.length >= 32) {
// Otherwise there'll be more than 2^32 subsets. And bitops will overflow in JS.
throw ArgumentError.value(elements, "elements", "must have less than 32 elements");
}
var list = [...elements];
var subsetCount = 1 << list.length;
for (var i = 0; i < subsetCount; i++) {
yield {
for (var j = 0, bit = 1; j < elements.length; j++, bit <<= 1)
if (i & bit != 0) list[j]
};
}
}
Another approach is to only have one set, and then update it iteratively to contain different elements. It's possible to go through all the sets doing only single-element changes on each step (using Gray-code):
/// Iterates a set through all combinations of its elements.
///
/// Adds and removes elements from [set] to make it iterate through all
/// possible combinations of its initial elements.
/// The current value of the iterator is always [set].
/// If iterated through to the end, the [set] ends up with all its original elements.
Iterable<Set<E>> subsets<E>(Set<E> set) sync* {
if (set.length >= 32) {
throw ArgumentError.value(set, "set", "must have less than 32 elements");
}
var list = [...set];
var prev = 0;
var counter = 0;
do {
yield set;
var next = ++counter ^ (counter >> 1);
var bit = prev ^ next; // One bit set.
var index = bit.bitLength - 1;
if (index >= list.length) index = 0;
var element = list[index];
if (next & bit == 0) {
set.add(element);
} else {
set.remove(element);
}
prev = next;
} while (set.length < list.length);
}
I've got a tree structure.
The task is to find the biggest sum/weight of path nodes, but i can only move n times. Thats ok, but going "up"/"back" cost nothing.
How can i accomplish that?
Below is my code, but the problem is that the each node can only be accessed once, so it doesnt work.
int mSum(Node* node, int mvLeft) {
if (node == nullptr) { return 0; }
if (mvLeft == 0) { return node->value; }
mvLeft--;
int sum = max(mSum(node->left, mvLeft), mSum(node->right, mvLeft));
return node->value + max(sum, mSum(node->parent, mvLeft + 1));
}
Here is the example graph. The numbers on the nodes represent the cost of getting to it. Each node can be visited only once except going "back".
The n step limit here is 3, we're counting entering the graph too, so the proper result is 21 because: 2->8->11.
If we would have limit of 4 steps the result would be 31: 2->10->8->11
My friend tried to do it with DFS, is he right? What's the best algorithm?
Good answer is taking multiple routes at the same time.
I mean we could go with 2-length limit:
2 left 0 right
1 left 1 right
0 left 2 right
Working, but somewhat slow, code :)
Its working time is 28s while other solutions can go with 2s (10 not known tests)
int mSum(Node* node, int mvLeft) {
mvLeft--;
if (mvLeft < 0) {
return 0;
}
else if (mvLeft == 0) {
return node->value;
}
if (node->left != nullptr && node->right != nullptr) {
int max = 0;
for (int i = 0; i <= mvLeft; i++) {
max = Max(max, mSum(node->left, i) + mSum(node->right, mvLeft - i));
}
return max + node->value;
}
else if (node->left != nullptr) {
return mSum(node->left, mvLeft) + node->value;
}
else if (node->right != nullptr) {
return mSum(node->right, mvLeft) + node->value;
}
return node->value;
}
Is there a better/faster way in Dart to rotate a list?
List<Object> rotate(List<Object> l, int i) {
i = i % l.length;
List<Object> x = l.sublist(i);
x.addAll(l.sublist(0, i));
return x;
}
Could be simplified a bit
List<Object> rotate(List<Object> list, int v) {
if(list == null || list.isEmpty) return list;
var i = v % list.length;
return list.sublist(i)..addAll(list.sublist(0, i));
}
If you want to shift instead of rotate you can simply use the removeAt function:
List<int> list = [ 1, 2, 3 ];
int firstElement = list.removeAt(0);
print(list); // [ 2, 3 ]
print(firstElement); // 1
From the docs:
Removes the object at position [index] from this list.
This method reduces the length of this by one and moves all later objects down by one position.
Returns the removed value.
The [index] must be in the range 0 ≤ index < length. The list must be growable.
Here are some more useful JS shims.