Is there any arithmetic formula that can test all given numbers are in row, like [ 3 5 4 ] - dart

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);
}

Related

Dart - Overflow Safe Summation of List

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)));

Max subtree sum in tree with limited 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;
}

Filtering IQueryable result set using parameters

I'm getting confused with this and I know there will be a more slick way of starting it off. The 'result' variable has many records and I want to check if IN_SiteId is > 0 and filter on it, same after that for LandownerId and PaymentCategoryId etc. If I can get the right approach for the first 2 I will be ok from there. This should be easier but having a brick wall day. Any comments appreciated
public IQueryable rptRentPaidMonthly(int IN_SiteId, int IN_LandownerId, int IN_PaymentCategoryId, int IN_PaymentTypeId, string IN_ShowRelevantProportion)
{
var result = this._lmsDb.rptRentPaidMonthly(IN_daysFrom, IN_daysTo, IN_SiteId, IN_LandownerId, IN_PaymentCategoryId, IN_PaymentTypeId, IN_ShowRelevantProportion);
if (IN_SiteId > 0)
{
var searchResults = (from s in result
where (s.SiteId == #IN_SiteId)
select s);
return searchResults.AsQueryable();
}
return result.AsQueryable();
}
I'm not a LINQ expert but I think you can do something like this:
public IQueryable rptRentPaidMonthly(int IN_SiteId, int IN_LandownerId, int IN_PaymentCategoryId, int IN_PaymentTypeId, string IN_ShowRelevantProportion)
{
var result = this._lmsDb.rptRentPaidMonthly(IN_daysFrom, IN_daysTo, IN_SiteId, IN_LandownerId, IN_PaymentCategoryId, IN_PaymentTypeId, IN_ShowRelevantProportion);
var searchResults = (from s in result
where (IN_SiteId <= 0 || s.SiteId == IN_SiteId)
&& (IN_LandownerId <= 0 || s.LandownerId == IN_LandownerId)
&& (IN_PaymentCategoryId <= 0 || s.PaymentCategoryId == IN_PaymentCategoryId)
&& (IN_PaymentTypeId <= 0 || s.PaymentTypeId == In_PaymentTypeId)
select s);
return searchResults.AsQueryable();
}
The where clause checks if each filter value is less than or equal to 0, if so then it will return true and will not evaluate the next bit which attempts to filter the actual field on the value provided.

linkedList insertionsort

This is my implementation for an insertion sort method using linkedList. I have tried it and it works just fine the only problem that there is an index out of bounds exception caused by the J+1 line. Can anyone tell me how to get around that or how to fix it. Thnx
public static <T extends Comparable <? super T>> void insertionSort2(List<T> portion){
int i = 0;
int j = 0;
T value;
//List <T> sorted = new LinkedList<T>();
// goes through the list
for (i = 1; i < portion.size(); i++) {
// takes each value of the list
value = (T) portion.remove(i);
// the index j takes the value of I and checks the rest of the array
// from the point i
j = i - 1;
while (j >= 0 && (portion.get(j).compareTo(value) >= 0)) {
portion.add(j+1 , portion.remove(j));//it was j+1
j--;
}
// put the value in the correct location.
portion.add(j + 1, value);
}
}
check this code out
just put it as a function in a class and try to call it
void InsertionSort()
{
int temp, out, in;
for(out=1 ; out<size ; out++)
{
temp = list[out];
in = out;
while (in > 0 && list[in-1] > temp)
{
list[in] = list[in-1];
--in;
}
list[in]= temp;
System.out.print("The list in this step became: ");
for (int t=0 ; t<size ; t++)
System.out.print(list[t]+" ");
System.out.println("");
}
}

Hash of a cell text in Google Spreadsheet

How can I compute a MD5 or SHA1 hash of text in a specific cell and set it to another cell in Google Spreadsheet?
Is there a formula like =ComputeMD5(A1) or =ComputeSHA1(A1)?
Or is it possible to write custom formula for this? How?
Open Tools > Script Editor then paste the following code:
function MD5 (input) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
var txtHash = '';
for (i = 0; i < rawHash.length; i++) {
var hashVal = rawHash[i];
if (hashVal < 0) {
hashVal += 256;
}
if (hashVal.toString(16).length == 1) {
txtHash += '0';
}
txtHash += hashVal.toString(16);
}
return txtHash;
}
Save the script after that and then use the MD5() function in your spreadsheet while referencing a cell.
This script is based on Utilities.computeDigest() function.
Thanks to gabhubert for the code.
This is the SHA1 version of that code (very simple change)
function GetSHA1(input) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_1, input);
var txtHash = '';
for (j = 0; j <rawHash.length; j++) {
var hashVal = rawHash[j];
if (hashVal < 0)
hashVal += 256;
if (hashVal.toString(16).length == 1)
txtHash += "0";
txtHash += hashVal.toString(16);
}
return txtHash;
}
Ok, got it,
Need to create custom function as explained in
http://code.google.com/googleapps/appsscript/articles/custom_function.html
And then use the apis as explained in
http://code.google.com/googleapps/appsscript/service_utilities.html
I need to handtype the complete function name so that I can see the result in the cell.
Following is the sample of the code that gave base 64 encoded hash of the text
function getBase64EncodedMD5(text)
{
return Utilities.base64Encode( Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, text));
}
The difference between this solution and the others is:
It fixes an issue some of the above solution have with offsetting the output of Utilities.computeDigest (it offsets by 128 instead of 256)
It fixes an issue that causes some other solutions to produce the same hash for different inputs by calling JSON.stringify() on input before passing it to Utilities.computeDigest()
function MD5(input) {
var result = "";
var byteArray = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, JSON.stringify(input));
for (i=0; i < byteArray.length; i++) {
result += (byteArray[i] + 128).toString(16) + "-";
}
result = result.substring(result, result.length - 1); // remove trailing dash
return result;
}
to get hashes for a range of cells, add this next to gabhubert's function:
function RangeGetMD5Hash(input) {
if (input.map) { // Test whether input is an array.
return input.map(GetMD5Hash); // Recurse over array if so.
} else {
return GetMD5Hash(input)
}
}
and use it in cell this way:
=RangeGetMD5Hash(A5:X25)
It returns range of same dimensions as source one, values will spread down and right from cell with formulae.
It's universal single-value-function to range-func conversion method (ref), and it's way faster than separate formuleas for each cell; in this form, it also works for single cell, so maybe it's worth to rewrite source function this way.
Based on #gabhubert but using array operations to get the hexadecimal representation
function sha(str){
return Utilities
.computeDigest(Utilities.DigestAlgorithm.SHA_1, str) // string to digested array of integers
.map(function(val) {return val<0? val+256 : val}) // correct the offset
.map(function(val) {return ("00" + val.toString(16)).slice(-2)}) // add padding and enconde
.join(''); // join in a single string
}
Using #gabhubert answer, you could do this, if you want to get the results from a whole row. From the script editor.
function GetMD5Hash(value) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, value);
var txtHash = '';
for (j = 0; j <rawHash.length; j++) {
var hashVal = rawHash[j];
if (hashVal < 0)
hashVal += 256;
if (hashVal.toString(16).length == 1)
txtHash += "0";
txtHash += hashVal.toString(16);
}
return txtHash;
}
function straightToText() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var r = 1;
var n_rows = 9999;
var n_cols = 1;
var column = 1;
var sheet = ss[0].getRange(r, column, n_rows, ncols).getValues(); // get first sheet, a1:a9999
var results = [];
for (var i = 0; i < sheet.length; i++) {
var hashmd5= GetMD5Hash(sheet[i][0]);
results.push(hashmd5);
}
var dest_col = 3;
for (var j = 0; j < results.length; j++) {
var row = j+1;
ss[0].getRange(row, dest_col).setValue(results[j]); // write output to c1:c9999 as text
}
}
And then, from the Run menu, just run the function straightToText() so you can get your result, and elude the too many calls to a function error.
I was looking for an option that would provide a shorter result. What do you think about this? It only returns 4 characters. The unfortunate part is that it uses i's and o's which can be confused for L's and 0's respectively; with the right font and in caps it wouldn't matter much.
function getShortMD5Hash(input) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
var txtHash = '';
for (j = 0; j < 16; j += 8) {
hashVal = (rawHash[j] + rawHash[j+1] + rawHash[j+2] + rawHash[j+3]) ^ (rawHash[j+4] + rawHash[j+5] + rawHash[j+6] + rawHash[j+7])
if (hashVal < 0)
hashVal += 1024;
if (hashVal.toString(36).length == 1)
txtHash += "0";
txtHash += hashVal.toString(36);
}
return txtHash.toUpperCase();
}
I needed to get a hash across a range of cells, so I run it like this:
function RangeSHA256(input)
{
return Array.isArray(input) ?
input.map(row => row.map(cell => SHA256(cell))) :
SHA256(input);
}

Resources