Why am I getting this NoSuchMethodError? - dart

I have this code
String encrypt(String x) {
String out;
var _x = x.codeUnits;
List dict;
/* <dict_assignment> */
dict[0] = 'a';
dict[1] = 'b';
dict[2] = 'c';
dict[3] = 'd';
dict[4] = 'e';
dict[5] = 'f';
dict[6] = 'g';
dict[7] = 'h';
dict[8] = 'i';
dict[9] = 'j';
/* </dict_assignment> */
_x.toList().forEach((i) {
var _i = i.toString();
_i.split("").forEach((k) {
var _k = int.parse(k);
print(_k);
print(dict[_k]);
out += dict[_k];
});
});
return out;
}
(Yes I'm writing HTML tags as comments in Dart...sue me)
(Idk why my indentations are messed up)
For some reason when I use this same function with a random string like this
var x = encrypt("hmm interesting");
I keep getting this
Unhandled exception:
NoSuchMethodError: The method '[]=' was called on null.
Receiver: null
Tried calling: []=(0, "a")
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
Please help me I'm actually confused why this is happening

You have not initialized your dict variable, so it contains null.
If you change List dict; to List dict = []; then that would start working.
You also haven't initialized out.
The remainder of the code is leaning towards being overly complicated, and can be optimized as well. Here is a suggestion:
String encrypt(String x) {
var out = StringBuffer();
const dict = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
for (var i in x.codeUnits) { // x.codeUnits is a list. Use for-in to iterate it.
for (var k in i.toString().codeUnits) {
var _k = k ^ 0x30; // Best way to convert code unit for 0-9 into integer 0-9.
// print(_k);
// print(dict[_k]);
out.write(dict[_k]); // Use a StringBuffer instead of repeated concatenation.
}
}
return out.toString();
}
It does not appear to be a decryptable encryption. The string "77" and the string "ᖳ" (aka "\u15b3") both encrypt to "ffff".
Or, if you want to "code-golf" rather than be readable or close to the original, it can also be a one-liner:
String encrypt(String x) => [
for (var i in x.codeUnits)
for (var k in "$i".codeUnits) "abcdefghij"[k ^ 0x30]
].join("");

Related

Why does my tree creation fail without the use of inline?

I'm trying to create a Trie structure in Zig using Zigs StringHashMap.
I am able to get it to work a bit, but only by using a "inline" for loop which is not really usable as this requires the paths to be known at compile time :-(
Any help/explanation would be much appreciated :-)
The code:
const std = #import("std");
const Allocator = std.mem.Allocator;
const print = std.debug.print;
const expect = std.testing.expect;
const HashMap = struct {
value: u8,
children: std.StringHashMap(*HashMap),
};
fn newHashMap(allocator: Allocator, value: u8) HashMap {
return HashMap{
.value = value,
.children = std.StringHashMap(*HashMap).init(allocator),
};
}
fn showTree(root: *std.StringHashMap(*HashMap), keys:[3][]const u8 ) void {
var hashMap = root;
for (keys) |key| {
print("get key {s}\n", .{key});
var value = hashMap.get(key);
if (value) |node| {
print("we got a value for {s}:{}\n", .{key,node.value});
hashMap = &node.children;
} else {
print("no value for {s}\n", .{key});
break;
}
}
}
test "HashMap" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const gpaAllocator = gpa.allocator();
var arena = std.heap.ArenaAllocator.init(gpaAllocator);
defer {
arena.deinit();
const leaked = gpa.deinit();
if (leaked) expect(false) catch #panic("TEST FAIL"); //fail test; can't try in defer as defer is executed after we return
}
const allocator = arena.allocator();
var root = &std.StringHashMap(*HashMap).init(allocator);
var hashMap = root;
const keys = [_][]const u8{ "a", "b", "c" };
const values: [3]u8 = .{ 1, 2, 3 };
// create tree
inline for (keys) |key, i| {
print("put key {s}:{}\n", .{ key, values[i] });
var newNode = newHashMap(allocator, values[i]);
try hashMap.put(key, &newNode);
showTree(root,keys);
hashMap = &newNode.children;
}
showTree(root,keys);
}
This prints:
Test [1/1] test "HashMap"...
put key a:1
put key b:2
put key c:3
get key a
we got a value for a:1
get key b
we got a value for b:2
get key c
we got a value for c:3
All 1 tests passed.
as expected.
Removing the 'inline' results in:
Test [1/1] test "HashMap"...
put key a:1
put key b:2
put key c:3
get key a
we got a value for a:3
get key b
no value for b
All 1 tests passed.
The answer turned out to be quite obvious (with hindsight ;-)) as mentioned in 1:
var declarations inside functions are stored in the function's stack frame. Once a function returns, any Pointers to variables in the function's stack frame become invalid references, and dereferencing them becomes unchecked Undefined Behavior.
This explains the strange behaviour in a loop without inline.
The pointers just get overwritten resulting in Undefined Behaviour.
By adding 'inline' the loop is unwound and then there is no pointer reuse, hence the correct output.
The correct way of dealing with this is to allocate the struct explicitly and pass around the pointer to the struct as shown in 2.
Once that is sorted it all makes sense.
https://ziglang.org/documentation/master/#Where-are-the-bytes
https://www.reddit.com/r/Zig/comments/s6v8t3/idiomatic_zig_for_initializing_an_allocated/
For reference, the working code without 'inline' below:
const std = #import("std");
const Allocator = std.mem.Allocator;
const print = std.debug.print;
const expect = std.testing.expect;
const HashMap = struct {
value: u8,
children: std.StringHashMap(*HashMap),
};
fn newHashMap(allocator: Allocator, value: u8) !*HashMap {
const node = try allocator.create(HashMap);
node.* = .{
.value = value,
.children = std.StringHashMap(*HashMap).init(allocator),
};
return node;
}
fn showTree(root: *std.StringHashMap(*HashMap), keys:[3][]const u8 ) void {
var hashMap = root;
for (keys) |key| {
print("get key {s}\n", .{key});
var value = hashMap.get(key);
if (value) |node| {
print("we got a value for {s}:{}\n", .{key,node.value});
hashMap = &node.children;
} else {
print("no value for {s}\n", .{key});
break;
}
}
}
test "HashMap" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const gpaAllocator = gpa.allocator();
var arena = std.heap.ArenaAllocator.init(gpaAllocator);
defer {
arena.deinit();
const leaked = gpa.deinit();
if (leaked) expect(false) catch #panic("TEST FAIL"); //fail test; can't try in defer as defer is executed after we return
}
const allocator = arena.allocator();
var root = &std.StringHashMap(*HashMap).init(allocator);
var hashMap = root;
const keys = [_][]const u8{ "a", "b", "c" };
const values: [3]u8 = .{ 1, 2, 3 };
// create tree
for (keys) |key, i| {
print("put key {s}:{}\n", .{ key, values[i] });
var newNode = try newHashMap(allocator, values[i]);
try hashMap.put(key, newNode);
hashMap = &newNode.children;
}
showTree(root,keys);
}

Check if element is the last value in fold function

I am using fold on an array which hasn't been assign to a variable and want to check whether the element is the last value. With a conventional for loop I can do this:
List<int> ints = [1, 2, 3];
int sum = 0;
for (int num in ints]) {
if (num != ints.last) {
sum = sum + num;
}
}
print(sum);
Is it possible to do this with fold instead?
int foldSum = [1, 2, 3].fold(0, (int prev, element) => prev + element);
print(foldSum);
I can't find any way of check when fold is at the last value. Note: this is a simplified example of my problem and the reason the list isn't assigned to a variable (allowing me to use .last) is because it is the result of a call to .map().
For completeness, below is the actual code (which won't obviously won't be runnable in isolation but will help illustrate my problem) I am trying to convert to use .map and .fold:
String get fieldsToSqlInsert {
String val = "";
for (Column column in columns) {
if (data.containsKey(column.name)) {
val = '$val "${data[column.name]}"';
} else {
val = "$val NULL";
}
if (column != columns.last) {
val = "$val,";
}
}
return val;
}
But it doesn't work because I don't know how to check when fold is at the final element:
String get fieldsToSqlInsert => columns
.map((column) =>
data.containsKey(column.name) ? data[column.name] : "NULL")
.fold("", (val, column) => column != columns.last ? "$val," : val);
If you simply want to exclude the last element from further calculation, you can just use take to do so:
String get fieldsToSqlInsert => columns.take(columns.length - 1)...

Move elements in a List?

Consider: ['A', 'B', 'C']
I'd like to do
list.move("B", -1);
list.move("A", 1);
resulting in ["B", "C", "A"].
Is there some sort of one liner to move items in a listin Dart? Obviously could do this manually in a few lines just curious if there is some easier way.
There is indeed no built-in way to do this.
Since the list keeps the same length, the most efficient approach would move the elements in-place rather than remove an element and then insert it again. The latter requires moving all later elements as well, where doing it in-place only requires moving the elements between from and to.
Example:
extension MoveElement<T> on List<T> {
void move(T element, int offset) {
var from = indexOf(element);
if (from < 0) return; // Or throw, whatever you want.
var to = from + offset;
// Check to position is valid. Or cap it at 0/length - 1.
RangeError.checkValidIndex(to, this, "target position", length);
element = this[from];
if (from < to) {
this.setRange(from, to, this, from + 1);
} else {
this.setRange(to + 1, from + 1, this, to);
}
this[to] = element;
}
}
I would probably prefer a more general "move" function like:
extension MoveElement<T> on List<T> {
void move(int from, int to) {
RangeError.checkValidIndex(from, this, "from", length);
RangeError.checkValidIndex(to, this, "to", length);
var element = this[from];
if (from < to) {
this.setRange(from, to, this, from + 1);
} else {
this.setRange(to + 1, from + 1, this, to);
}
this[to] = element;
}
}
and then build the "find element, then move it relative to where it was" on top of that.
linear? I don't think there is any. In any case, a sample code here:
extension on List<String> {
void move(String element, int shift) {
if (contains(element)) {
final curPos = indexOf(element);
final newPos = curPos + shift;
if (newPos >= 0 && newPos < length) {
removeAt(curPos);
insert(newPos, element);
}
}
}
}
void main(List<String> args) {
var list = ['A', 'B', 'C', 'D', 'E', 'F'];
print(list);
list.move('B', 2);
print(list);
list.move('B', -3);
print(list);
}
Result:
[A, B, C, D, E, F]
[A, C, D, B, E, F]
[B, A, C, D, E, F]

Dart - get the nearest(larger) value from List?

How can I find the closest value in a list, which will return me the higher value?
Example: List of [3,7,12,19] if my value is 8 how can I get the nearest(larger) value 12? i want this logic in dart.
Just filter the List only for the values higher or equal to your number and get the lowest value:
var n = 8; // Number to match
var l = [3, 7, 12, 19]; // List of values
var greater = l.where((e) => e >= n).toList()..sort(); //List of the greater values
print(greater.first); // Print the first value. -> 12
To get Closest Value of number
import 'dart:math';
import 'dart:collection';
void main(){
List<double> value = [1,4,6,3,7,9,12,34,12,-12,-91];
print(value.getCloseValue(8)); // 7
print(value.getCloseValue(6)); // 6
print(value.getCloseValue(-11)); // -12
}
extension on List<num> {
num getCloseValue(num x) {
if (isEmpty) return 0;
Map<num, num> values = {};
forEach((e) {
values[e] = (e - x).abs();
});
var sortedKeys = values.keys.toList(growable:false)
..sort((k1, k2) => values[k1]!.compareTo(values[k2]!));
final sortedMap = LinkedHashMap
.fromIterable(sortedKeys, key: (k) => k, value: (k) => values[k]);
return sortedMap.keys.first;
}
}
List<int> arr = [6, 12, 11, 18, 24,5,6,99,10,9];
arr.sort((a, b) => a.compareTo(b));
print(arr);
print(Utils.getNextLargerNumber(8, arr));
and below is the logic:
static int getNextLargerNumber(int number, List<int> array)
{
for (var i = 0; i < array.length; i++) {
if (number < array[i]) {
return array[i];
}
}
return -1;
}
Mattia's answer is already good enough. (although the list cant have the length 0 and it might be not as efficient, as you have a where() as well as sort() in there). Here is a different approach, that solves those concerns:
Nearest value to target (larger favored)
final nearestLarger = list.isEmpty ? null : list.reduce(
(a, b) => (a-target).abs() < (b -target).abs() ? a : b);
Nearest value to target (smaller favoured)
final nearestSmaller = list.isEmpty ? null : list.reduce(
(a, b) => (a-target).abs() <= (b -target).abs() ? a : b);
Note that both functions retrieve the nearest value to the target, but in case of ambiguity (eg. [3,4,5]) either the bigger or smaller value is favored.

String Split in DXL

I have a string
Ex: "We prefer questions that can be answered; not just discussed "
now i want to split this string from ";"
like
We prefer questions that can be answered
and
not just discussed
is this possible in DXL.
i am learning DXL, so i don't have any idea whether we can split or not.
Note : This is not a home work.
I'm sorry for necroing this post. Being new to DXL I spent some time with the same challenge. I noticed that the implementations available on the have different specifications of "splitting" a string. Loving the Ruby language, I missed an implementation which comes at least close to the Ruby version of String#split.
Maybe my findings will be helpful to anybody.
Here's a functional comparison of
Variant A: niol's implementation (which at a first glance, appears to be the same implementation which is usually found at Capri Soft,
Variant B: PJT's implementation,
Variant C: Brett's implementation and
Variant D: my implementation (which provides the correct functionality imo).
To eliminate structural difference, all implementations were implemented in functions, returning a Skip list or an Array.
Splitting results
Note that all implementations return different results, depending on their definition of "splitting":
string mellow yellow; delimiter ello
splitVariantA returns 1 elements: ["mellow yellow" ]
splitVariantB returns 2 elements: ["m" "llow yellow" ]
splitVariantC returns 3 elements: ["w" "w y" "" ]
splitVariantD returns 3 elements: ["m" "w y" "w" ]
string now's the time; delimiter
splitVariantA returns 3 elements: ["now's" "the" "time" ]
splitVariantB returns 2 elements: ["" "now's the time" ]
splitVariantC returns 5 elements: ["time" "the" "" "now's" "" ]
splitVariantD returns 3 elements: ["now's" "the" "time" ]
string 1,2,,3,4,,; delimiter ,
splitVariantA returns 4 elements: ["1" "2" "3" "4" ]
splitVariantB returns 2 elements: ["1" "2,,3,4,," ]
splitVariantC returns 7 elements: ["" "" "4" "3" "" "2" "" ]
splitVariantD returns 7 elements: ["1" "2" "" "3" "4" "" "" ]
Timing
Splitting the string 1,2,,3,4,, with the pattern , for 10000 times on my machine gives these timings:
splitVariantA() : 406 ms
splitVariantB() : 46 ms
splitVariantC() : 749 ms
splitVariantD() : 1077 ms
Unfortunately, my implementation D is the slowest. Surprisingly, the regular expressions implementation C is pretty fast.
Source code
// niol, modified
Array splitVariantA(string splitter, string str){
Array tokens = create(1, 1);
Buffer buf = create;
int str_index;
buf = "";
for(str_index = 0; str_index < length(str); str_index++){
if( str[str_index:str_index] == splitter ){
array_push_str(tokens, stringOf(buf));
buf = "";
}
else
buf += str[str_index:str_index];
}
array_push_str(tokens, stringOf(buf));
delete buf;
return tokens;
}
// PJT, modified
Skip splitVariantB(string s, string delimiter) {
int offset
int len
Skip skp = create
if ( findPlainText(s, delimiter, offset, len, false)) {
put(skp, 0, s[0 : offset -1])
put(skp, 1, s[offset +1 :])
}
return skp
}
// Brett, modified
Skip splitVariantC (string s, string delim) {
Skip skp = create
int i = 0
Regexp split = regexp "^(.*)" delim "(.*)$"
while (split s) {
string temp_s = s[match 1]
put(skp, i++, s[match 2])
s = temp_s
}
put(skp, i++, s[match 2])
return skp
}
Skip splitVariantD(string str, string pattern) {
if (null(pattern) || 0 == length(pattern))
pattern = " ";
if (pattern == " ")
str = stringStrip(stringSqueeze(str, ' '));
Skip result = create;
int i = 0; // index for searching in str
int j = 0; // index counter for result array
bool found = true;
while (found) {
// find pattern
int pos = 0;
int len = 0;
found = findPlainText(str[i:], pattern, pos, len, true);
if (found) {
// insert into result
put(result, j++, str[i:i+pos-1]);
i += pos + len;
}
}
// append the rest after last found pattern
put(result, j, str[i:]);
return result;
}
Quick join&split I could come up with. Seams to work okay.
int array_size(Array a){
int size = 0;
while( !null(get(a, size, 0) ) )
size++;
return size;
}
void array_push_str(Array a, string str){
int array_index = array_size(a);
put(a, str, array_index, 0);
}
string array_get_str(Array a, int index){
return (string get(a, index, 0));
}
string str_join(string joiner, Array str_array){
Buffer joined = create;
int array_index = 0;
joined += "";
for(array_index = 0; array_index < array_size(str_array); array_index++){
joined += array_get_str(str_array, array_index);
if( array_index + 1 < array_size(str_array) )
joined += joiner;
}
return stringOf(joined)
}
Array str_split(string splitter, string str){
Array tokens = create(1, 1);
Buffer buf = create;
int str_index;
buf = "";
for(str_index = 0; str_index < length(str); str_index++){
if( str[str_index:str_index] == splitter ){
array_push_str(tokens, stringOf(buf));
buf = "";
}else{
buf += str[str_index:str_index];
}
}
array_push_str(tokens, stringOf(buf));
delete buf;
return tokens;
}
If you only split the string once this is how I would do it:
string s = "We prefer questions that can be answered; not just discussed"
string sub = ";"
int offset
int len
if ( findPlainText(s, sub, offset, len, false)) {
/* the reason why I subtract one and add one is to remove the delimiter from the out put.
First print is to print the prefix and then second is the suffix.*/
print s[0 : offset -1]
print s[offset +1 :]
} else {
// no delimiter found
print "Failed to match"
}
You could also use regular expressions refer to the DXL reference manual. It would be better to use regular expressions if you want to split up the string by multiple delimiters such as str = "this ; is an;example"
ACTUALLY WORKS:
This solution will split as many times as needed, or none, if the delimiter doesn't exist in the string.
This is what I have used instead of a traditional "split" command.
It actually skips the creation of an array, and just loops through each string that would be in the array and calls "someFunction" on each of those strings.
string s = "We prefer questions that can be answered; not just discussed"
// for this example, ";" is used as the delimiter
Regexp split = regexp "^(.*);(.*)$"
// while a ";" exists in s
while (split s) {
// save the text before the last ";"
string temp_s = s[match 1]
// call someFunction on the text after the last ";"
someFunction(s[match 2])
// remove the text after the last ";" (including ";")
s = temp_s
}
// call someFunction again for the last (or only) string
someFunction(s)
Sorry for necroing an old post; I just didn't find the other answers useful.
Perhaps someone would find handy this fused solution as well. It splits string in Skip, based on delimiter, which can actually have length more then one.
Skip splitString(string s1, string delimit)
{
int offset, len
Skip splited = create
while(findPlainText(s1, delimit, offset, len, false))
{
put(splited, s1[0:offset-1], s1[0:offset-1])
s1 = s1[offset+length(delimit):length(s1)-1]
}
if(length(s1)>0)
{
put (splited, s1, s1)
}
return splited
}
I tried this out and worked out for me...
string s = "We prefer questions that can be answered,not just discussed,hiyas"
string sub = ","
int offset
int len
string s1=s
while(length(s1)>0){
if ( findPlainText(s1, sub, offset, len, false)) {
print s1[0 : offset -1]"\n"
s1= s1[offset+1:length(s1)]
}
else
{
print s1
s1=""
}
}
Here is a better implementation. This is a recursive split of the string by searching a keyword.
pragma runLim, 10000
string s = "We prefer questions that can be answered,not just discussed,hiyas;
Next Line,Var1,Nemesis;
Next Line,Var2,Nemesis1;
Next Line,Var3,Nemesis2;
New,Var4,Nemesis3;
Next Line,Var5,Nemesis4;
New,Var5,Nemesis5;"
string sub = ","
int offset
int len
string searchkey=null
string curr=s
string nxt=s
string searchline=null
string Modulename=""
string Attributename=""
string Attributevalue=""
while(findPlainText(curr,"Next Line", offset,len,false))
{
int intlen=offset
searchkey=curr[offset:length(curr)]
if(findPlainText(searchkey,"Next Line",offset,len,false))
{
curr=searchkey[offset+1:length(searchkey)]
}
if(findPlainText(searchkey,";",offset,len,false))
{
searchline=searchkey[0:offset]
}
int counter=0
while(length(searchline)>0)
{
if (findPlainText(searchline, sub, offset, len, false))
{
if(counter==0)
{
Modulename=searchline[0 : offset -1]
counter++
}
else if(counter==1)
{
Attributename=searchline[0 : offset -1]
counter++
}
searchline= searchline[offset+1:length(searchline)]
}
else
{
if(counter==2)
{
Attributevalue=searchline[0:length(searchline)-2]
counter++
}
searchline=""
}
}
print "Modulename="Modulename " Attributename=" Attributename " Attributevalue= "Attributevalue "\n"
}

Resources