Dart While Loop usage - dart

i have a logic mistake but i cant figure out, loop not stops when num= returnitemcount ?
void main() {
List<int> listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
List<int> exceptions = [2, 3, 4];
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) {
List<int> returnlist = [];
int num = 0;
while (num < returnitemcount) {
for (var i = 0; i < listfrom.length; i++) {
if (!exceptions.contains(listfrom[i])) {
returnlist.add(listfrom[i]);
num++;
}
}
}
return returnlist;
}
List<int> mylist = exceptedlist(3, exceptions, listAll);
print(mylist);
// expected => 1,5,6
// result => 1, 5, 6, 7, 8, 9
}

Your problem is that your while are only evaluated twice. The first time num is 0 and the second time it is 6. It is not evaluated every time num is updated.
while loops does not mean that the code inside the block are running as long some statement are true. It means the code will loop as long the statement are true.
So what you need to do is to check num every time you update the value. Something like this:
void main() {
List<int> listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
List<int> exceptions = [2, 3, 4];
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) {
List<int> returnlist = [];
int num = 0;
while (num < returnitemcount) {
for (var i = 0; i < listfrom.length; i++) {
if (!exceptions.contains(listfrom[i])) {
returnlist.add(listfrom[i]);
if (++num >= returnitemcount) {
break;
}
}
}
}
return returnlist;
}
List<int> mylist = exceptedlist(3, exceptions, listAll);
print(mylist); // [1, 5, 6]
}
I am not sure what you code are going to do exactly but you should be able to skip the while loop:
void main() {
List<int> listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
List<int> exceptions = [2, 3, 4];
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) {
List<int> returnlist = [];
for (var i = 0; i < listfrom.length; i++) {
if (!exceptions.contains(listfrom[i])) {
returnlist.add(listfrom[i]);
if (returnlist.length >= returnitemcount) {
break;
}
}
}
return returnlist;
}
List<int> mylist = exceptedlist(3, exceptions, listAll);
print(mylist); // [1, 5, 6]
}
And can properly even be shorten into:
void main() {
final listAll = [1, 2, 3, 4, 5, 6, 7, 8, 9];
final exceptions = [2, 3, 4];
final mylist = exceptedlist(3, exceptions, listAll);
print(mylist); // [1, 5, 6]
}
List<int> exceptedlist(
int returnitemcount, List<int> exceptions, List<int> listfrom) =>
listfrom
.where((element) => !exceptions.contains(element))
.take(returnitemcount)
.toList();

Related

How to break from middle of generator in dart?

How can I break from dart generator based on some condition?
fn sync*(...){
yield 1;
yield 2;
if(someCondition()) //cancel/break the generator
yield 3;
if(someCondition2()) //cancel/break the generator
yield 4;
if(someCondition4()) //cancel/break the generator
yield 5;
}
Simply return from your generator when you want it to stop generating new values:
Iterable<int> fn(bool flag) sync* {
yield 1;
yield 2;
if (flag) {
return;
}
yield 3;
}
void main() {
print(fn(true).toList()); // Prints: [1, 2]
print(fn(false).toList()); // Prints: [1, 2, 3]
}

Palindrome Number time limit exceeded error dart

First i want to say that i am trying to solve Palindrome Number problem on LeetCode using dart, of course
https://leetcode.com/problems/palindrome-number/
So far I have tried total 6 different method to solve the problem.
And am not very happy to say that all of them leading to time limit exceeded error on LeetCode.. Solutions are perfectly working on terminal because of the less test cases but when submit, and it tried on large number it ends up error.
My 6 solutions based on different classes.each class contain their own implemented solution..
I dont know if the while loop in dart is slow or something wrong with the leetcode
class A {
bool isPalindrome(int x) {
if (x < 0) {
return false;
}
double divisor = 1;
while (x / divisor >= 10) {
divisor *= 10;
}
while (x != 0) {
if ((x / divisor).truncate() != (x % 10).floor()) {
return false;
}
x %= divisor.toInt();
x = (x / 10).floor();
divisor /= 100;
}
return true;
}
}
class B {
bool isPalindrome(int x) {
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revNum = 0;
while (x > revNum) {
revNum = revNum * 10 + x % 10;
x = (x / 10).floor();
}
return (x == revNum || x == revNum / 10);
}
}
class C {
bool isPalindrome(int x) {
if (x < 0) {
return false;
}
int y = 0;
int xx = x;
if (xx > 0) {
y = y * 10 + xx % 10;
xx = (xx / 10).floor();
}
return (y != x);
}
// while (xx > 0) {
// y = y * 10 + xx % 10;
// xx = (xx / 10).floor();
// }
}
class D {
bool isPalindrome(int x) {
if (x.isNegative) return false;
final list = convert(x);
for (var i = 0; i < (list.length ~/ 2); i++) {
if (list[i] != list[list.length - 1 - i]) return false;
}
return true;
}
List convert(int x) {
final List<int> list = <int>[];
while (x > 0) {
list.add(x % 10);
x = x ~/ 10;
}
return list;
}
}
class F {
bool isPalindrome(int x) {
if (x.isNegative) return false;
if (x == 0) return true;
if (x % 10 == 0) return false;
var reverted = 0, iter = x;
while (iter > 0) {
reverted = reverted * 10;
reverted += iter % 10;
iter = iter ~/ 10;
}
return reverted == x;
}
}
class G {
bool isPalindrome(int x) {
if (x.isNegative) return false;
var tens = 10;
while (tens < x) tens *= 10;
tens = tens ~/ 10;
while (x > 10) {
var lastDigit = x % 10;
var firstDigit = x ~/ tens;
if (lastDigit != firstDigit) return false;
x -= firstDigit * tens;
x = x ~/ 10;
tens = tens ~/ 100;
}
return true;
}
}
I'm pretty sure the leetcode site has a problem here.
I don't know what they're using their time on, but it seems impossible to get a correct result without a timeout.
My attempted solutions are:
class Solution2 {
// No intermediate allocations, only number operations.
bool isPalindrome(int x) {
if (x < 0) return false;
if (x < 10) return true;
int r = 0;
do {
var d = x.remainder(10);
x = x ~/ 10;
if (r == x) return true; // Odd length number
r = r * 10 + d;
if (r == x) return true; // Even length number
if (r == 0) return false; // Trailing zero
} while (r < x);
return false;
}
}
class Solution3 {
// Just do toString and check that it's a palindrome.
// Integer.toString is heavily optimized already.
bool isPalindrome(int x) {
if (x < 0) return false;
if (x < 10) return true;
var s = x.toString();
for (var i = 0, j = s.length - 1; i < j; i++, j--) {
if (s.codeUnitAt(i) != s.codeUnitAt(j)) return false;
}
return true;
}
}
If those are not fast enough, I seriously doubt anything will be.
I even considered whether repeatedly dividing by 10 was incredibly slow for some reason, so I switched to dividing by 100 instead, which should halve the divisions.
class Solution {
// Minimize divisions by dividing by 100, and do lookup for the digits.
static const digits =[
0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9,
1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9,
2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9,
3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 5, 3, 6, 3, 7, 3, 8, 3, 9,
4, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4, 5, 4, 6, 4, 7, 4, 8, 4, 9,
5, 0, 5, 1, 5, 2, 5, 3, 5, 4, 5, 5, 5, 6, 5, 7, 5, 8, 5, 9,
6, 0, 6, 1, 6, 2, 6, 3, 6, 4, 6, 5, 6, 6, 6, 7, 6, 8, 6, 9,
7, 0, 7, 1, 7, 2, 7, 3, 7, 4, 7, 5, 7, 6, 7, 7, 7, 8, 7, 9,
8, 0, 8, 1, 8, 2, 8, 3, 8, 4, 8, 5, 8, 6, 8, 7, 8, 8, 8, 9,
9, 0, 9, 1, 9, 2, 9, 3, 9, 4, 9, 5, 9, 6, 9, 7, 9, 8, 9, 9,
];
bool isPalindrome(int x) {
if (x < 0) return false;
if (x < 10) return true;
int r = 0;
do {
var d = x.remainder(100);
x = x ~/ 100;
var d1 = digits[d * 2];
var d2 = digits[d * 2 + 1];
if (r == x && d1 == d2) return true; // Even length number
if (r == x * 10 + d1) return true; // Odd length number.
r = r * 10 + d2;
if (r == 0) return false; // Trailing zero
if (r == x) return true; // Odd length number
r = r * 10 + d1;
if (r == x) return true; // Even length number
} while (r < x);
return false;
}
}
Still times out.

Dart | Is there any way to convert List<int> to int?

I'd like to convert List<int> to int like so.
List<int> list = [18, 30];
Result:
int convertedInt = 1830;
Is there any way?
void main() {
List<int> x = [18,30];
var y = x.join(''); // Concatenate each element of list
int z = int.parse(y); // Convert that to int
print(z);
}
void main() {
List<int> list = [18, 30,1,101];
int convertedInt = 1830;
String a = '';
print(list);
list.forEach((element) => a = a + ((element>99) ? '**' : element.toString().padLeft(2,'0')) );
print(a);
}
output:
[18, 30, 1, 101]
183001**
Number less than 10 will get a leading zero, and number larger than 99 will be converted to '**', to make clear they do not fit in two positions.
List<int> list = [18, 30];
var result = BigInt.parse(encode(Uint8List.fromList(list)),radix: 16)
///list to hex string
static String encode(Uint8List? bytes) {
if (bytes == null) return '';
var result = StringBuffer();
for (var i = 0; i < bytes.lengthInBytes; i++) {
var part = bytes[i];
result.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}');
}
return result.toString();
}

Dart - Matrix Spiral

I'm trying to solve this common interview question but I'm getting a RangeError: Valid value range is empty in the body of the first for loop (results[startColumn][i] = counter;)
The problem is Given an integer n, generate a square matrix filled with elements in spiral order.
For example, Given n = 3,
You should return the following matrix: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
This is my solution:
void matrix(int n) {
List<List> results = [];
for (var i = 0; i < n; i++) {
results.add([]);
}
int counter = 1;
int startColumn = 0;
int endColumn = n - 1;
int startRow = 0;
int endRow = n - 1;
while (startColumn <= endColumn && startRow <= endRow) {
// Top row
for (var i = startColumn; i <= endColumn; i++) {
results[startColumn][i] = counter;
counter++;
}
startRow++;
// Right column
for (var i = startRow; i <= endRow; i++) {
results[endColumn][i] = counter;
counter++;
}
endColumn--;
// Bottom row
for (var i = endColumn; i >= startColumn; i--) {
results[endRow][i] = counter;
counter++;
}
endRow--;
// Start column
for (var i = endRow; i >= startRow; i--) {
results[startColumn][i] = counter;
counter++;
}
startColumn++;
}
print(results);
}
Any ideas why its going out of bounds? 0,0 should really be the first index of the first inner List so I'm not sure why its out of bounds?
Well, the range error is about the results list is not initialized completely. You are inserting empty lists to the list but these lists are empty so you cannot ask for a specific element like
(not even for inserting an element to the list) results[startColumn][i].
So you need to specify a length to the lists you are adding to your results list:
final results = <List<int>>[];
for (var i = 0; i < n; i++) {
results.add(List<int>(n));
}
By making that change the code now "works" and gives the following results:
[[1, 8, 3], [null, 9, null], [7, 6, 5]]
Since your question was about the "range error" I guess fixing your matrix method is out of scope. But please tell me if you also want me to take a look at it. :)
Updated with answer to the Matrix problem
You were really close with the solution but with using a debugger it becomes clear that you have a problem when updating vertical rows. This can be seen when you makes the update for Right column and Start column.
The full solution looks like the following (I have added comments the two places I made some changes):
void matrix(int n) {
final results = <List<int>>[];
for (var i = 0; i < n; i++) {
results.add(List<int>(n));
}
int counter = 1;
int startColumn = 0;
int endColumn = n - 1;
int startRow = 0;
int endRow = n - 1;
while (startColumn <= endColumn && startRow <= endRow) {
// Top row
for (var i = startColumn; i <= endColumn; i++) {
results[startColumn][i] = counter;
counter++;
}
startRow++;
// Right column
for (var i = startRow; i <= endRow; i++) {
results[i][endColumn] = counter; // Switched i and endColumn
counter++;
}
endColumn--;
// Bottom row
for (var i = endColumn; i >= startColumn; i--) {
results[endRow][i] = counter;
counter++;
}
endRow--;
// Start column
for (var i = endRow; i >= startRow; i--) {
results[i][startColumn] = counter; // Switched i and startColumn
counter++;
}
startColumn++;
}
print(results);
}
And when running the code it should give the following results:
matrix(2); // [[1, 2], [4, 3]]
matrix(3); // [[1, 2, 3], [8, 9, 4], [7, 6, 5]]
matrix(4); // [[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]]

Unable to access 6 channel Mat of type 16UC(6)

I am unable to access a Mat of type 16UC(6). Below is the code used to iterate over the Mat.
//6 channel Mat
int cols=1280, rows=720;
Mat mat1=Mat(cols, rows, CV_16UC(6), Scalar::all(0));
Mat grid(Size(cols, rows), CV_16UC2, Scalar::all(0));
//create a grid of numbers - the value of each pixel in the grid
contains the coordinate of the pixel
for (int i = 0; i < grid.rows; ++i) {
for (int j = 0; j < grid.cols; ++j) {
grid.at<Vec2s>(i, j)[0] = (ushort)j;
grid.at<Vec2s>(i, j)[1] = (ushort)i;
}
}
vector<Mat> imgs(2); //create copies of the grid for each image
for(int i=0;i<2;i++){
imgs[i] = grid.clone();
}
//Values in Mat1 are filled with values of imgs[0] and imgs[1] using
// some logic.
int rows=mat1.rows;
int channels=mat1.channels();
int cols=mat1.cols * channels;
uchar* p;
for(int i=0;i<rows;i++){
p=mat1.ptr<uchar>(i);
for(int j=0;j<cols;j+=6){
cout<<"Value 0 :"<<p[j]<<endl;
cout<<"Value 1 :"<<p[j+1]<<endl;
cout<<"Value 2 :"<<p[j+2]<<endl;
cout<<"Value 3 :"<<p[j+3]<<endl;
cout<<"Value 4 :"<<p[j+4]<<endl;
cout<<"Value 5 :"<<p[j+5]<<endl;
}
}
But im getting ^E and ^# as values. When tried casting to (int) I am getting all zeros.
I am able to access the Mat properly using MatIterator. I am not sure where I went wrong, there must be some issue with the Mat ype and the way I am trying to access the value.Can anyone help me in solving the issue.
You have:
grid.at<Vec2s>(i, j)[0] = (ushort)j;
Vec2s is for shorts, but you have Unsigned Short matrix. You should use Vec2w (not sure who came with the w... or why) that is for unsigned short.
This can be rewritten as:
grid.at<cv::Vec2w>(i, j)[0] = static_cast<ushort>(j);
Then, you show uchar values from the 16U matrix... each uchar is 8bit and each pixel is 16bit...
Here is an example of how you can access each pixel with iterators in a CV_16UC(6) matrix.
// create dummy 3x3 matrix
cv::Mat b(3,3,CV_16UC(6));
// use the templated functions begin and end (you may templated with <ushort>
// directly and it will represent the value of each channel of each pixel)
for (auto it = b.begin<cv::Vec<ushort, 6>>(); it != b.end<cv::Vec<ushort, 6>>(); ++it)
{
// assign some values (this part can be skipped if it is already filled)
(*it)[0] = 5;
(*it)[1] = 7;
(*it)[2] = 8;
(*it)[3] = 9;
(*it)[4] = 1;
(*it)[5] = 2;
// Print the Vec<ushort, 6>, OpenCV already has a way to print it
std::cout << *it << std::endl;
}
And the result of this small code is:
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
[5, 7, 8, 9, 1, 2]
Which is what we expect. You may have notice that I used cv::Vec<ushort, 6>, cv::Vec can be templated with any number of channels (probably there is a limit) and any type (I have only tested it with native numeric types). Actually cv::Vec2w or cv::Vec2s are just typedef of cv::Vec and cv::Vec respectively, and you can also create your typedef if you use it all over the code.
using Vec6w = cv::Vec<ushort, 6>;
and then you can replace it in the for loop:
...
for (auto it = b.begin<Vec6w>(); it != b.end<Vec6w>(); ++it)
...
and achieve the same result

Resources