General insertion sort algorithm not moving the first object in list - c++17

I need to create a general insertion sort algorithm using move semantics. I have it working for entire lists of different types of objects except for the very first object in the list.
template<typename Iter, typename Comparator>
void insertionSort(const Iter& begin, const Iter& end, Comparator compareFn)
{
for (auto i = begin + 1; i < end; i++)
{
auto currentthing = std::move(*i);
auto j = std::move(i - 1);
while (j >= begin and compareFn(*j, currentthing))
{
*(j + 1) = std::move(*j);
if (j == begin)
break;
j--;
}
*(j + 1) = std::move(currentthing);
}
}
Where comparing a list of strings from my main function:
int main()
{
vector<int> numbers = { 0, 1, 8, 4, 2, 9, 5, 3, 6, 7, 10 };
insertionSort(numbers.begin(), numbers.end(), std::less<int>());
cout << "Sorted: " << numbers << "\n";
vector<string> names = { "p", "a", "b", "d", "c", "f", "e" };
insertionSort(names.begin(), names.end(), std::greater<string>());
cout << "Sorted: " << names << "\n";
return 0;
}
Outputs the following
Sorted: [ 0 10 9 8 7 6 5 4 3 2 1 ]
Sorted: [ a b c d e f ]

The while loop should break when j equals i and not when j equals begin. So, the following:
if (j == begin)
break;
should actually be:
if (j == i)
break;

Related

Why is the containsKey() function not detecting the repeated char as the key in Dart in the problem below?

The containsKey() function is not detecting the repeated value in my test 'current' string, where it just replaces the original value of the key 'r' with 3, when it should go through the containsKey() function, as see that there is a value at 2, and then replace that key with a new one.
void main(){
Map<String, String> split = new Map();
var word = 'current ';
for (int i = 0; i < word.length; i++) {
String temp = word[i];
if (split.containsKey([temp])) {
split[temp] = split[temp]! + ' ' + i.toString();
} else {
split[temp] = i.toString();
}
}
print(split.toString());
}
The output produces
{c: 0, u: 1, r: 3, e: 4, n: 5, t: 6}
while I want it to produce {c: 0, u: 1, r: 2 3, e: 4, n: 5, t: 6}
It is because you are doing split.containsKey([temp]) instead of split.containsKey(temp).
In your snippet, you are checking whether the map split has the array [temp] as a key, (in the case of 'r': ['r']), which is false, it has 'r' as a key, not ['r'].
Change your code to
void main(){
Map<String, String> split = new Map();
var word = 'current ';
for (int i = 0; i < word.length; i++) {
String temp = word[i];
if (split.containsKey(temp)) { // <- Change here.
split[temp] = split[temp]! + ' ' + i.toString();
} else {
split[temp] = i.toString();
}
}
print(split.toString());
}

Dart: how to convert a column letter into number

Currently using Dart with gsheets_api, which don't seem to have a function to convert column letters to numbers (column index)
As an example , this is what I use with AppScript (input: column letter, output: column index number):
function Column_Nu_to_Letter(column_nu)
{
var temp, letter = '';
while (column_nu > 0)
{
temp = (column_nu - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column_nu = (column_nu - temp - 1) / 26;
}
return letter;
};
This is the code I came up for Dart, it works, but I am sure there is a more elegant or correct way to do it.
String colLetter = 'L'; //Column 'L' as example
int c = "A".codeUnitAt(0);
int end = "Z".codeUnitAt(0);
int counter = 1;
while (c <= end) {
//print(String.fromCharCode(c));
if(colLetter == String.fromCharCode(c)){
print('Conversion $colLetter = $counter');
}
counter++;
c++;
}
// this output L = 12
Do you have any suggestions on how to improve this code?
First we need to agree on the meaning of the letters.
I believe the traditional approach is "A" is 1, "Z" is 26, "AA" is 27, "AZ" is 52, "BA" is 53, etc.
Then I'd probably go with something like these functions for converting:
int lettersToIndex(String letters) {
var result = 0;
for (var i = 0; i < letters.length; i++) {
result = result * 26 + (letters.codeUnitAt(i) & 0x1f);
}
return result;
}
String indexToLetters(int index) {
if (index <= 0) throw RangeError.range(index, 1, null, "index");
const _letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (index < 27) return _letters[index - 1];
var letters = <String>[];
do {
index -= 1;
letters.add(_letters[index.remainder(26)]);
index ~/= 26;
} while (index > 0);
return letters.reversed.join("");
}
The former function doesn't validate that the input only contains letters, but it works correctly for strings containing only letters (and it ignores case as a bonus).
The latter does check that the index is greater than zero.
A simplified version base on Irn's answer
int lettersToIndex(String letters) =>
letters.codeUnits.fold(0, (v, e) => v * 26 + (e & 0x1f));
String indexToLetters(int index) {
var letters = '';
do {
final r = index % 26;
letters = '${String.fromCharCode(64 + r)}$letters';
index = (index - r) ~/ 26;
} while (index > 0);
return letters;
}

how do I make an integer to roman algorithm in dart?

I want to write an algorithm that converts integer numbers to roman numbers and supports any positive number in dart.
I can do this in Java using String builder and i tried to do it in dart but i failed.
so please if anyone could help me, that would be very much appreciated!
here is the java algorithm, maybe it would help:
public static int[] arabianRomanNumbers = new int[]{
1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
};
public static String[] romanNumbers = new String[]{
"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
};
public String intToRoman(int num) {
if (num < 0) return "";
else if (num == 0) return "nulla";
StringBuilder builder = new StringBuilder();
for (int a = 0; a < arabianRomanNumbers.length; a++) {
int times = num / arabianRomanNumbers[a]; // equals 1 only when arabianRomanNumbers[a] = num
// executes n times where n is the number of times you have to add
// the current roman number value to reach current num.
builder.append(romanNumbers[a].repeat(times));
num -= times * arabianRomanNumbers[a]; // subtract previous roman number value from num
}
return builder.toString();
}
StringBuilder is called StringBuffer in Dart and does nearly the same but with a little different interface which you can read more about in the API documentation:
https://api.dart.dev/stable/2.7.1/dart-core/StringBuffer-class.html
With this knowledge, I have converted your Java code into Dart:
const List<int> arabianRomanNumbers = [
1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
];
const List<String> romanNumbers = [
"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
];
String intToRoman(int input) {
var num = input;
if (num < 0) {
return "";
}
else if (num == 0) {
return "nulla";
}
final builder = StringBuffer();
for (var a = 0; a < arabianRomanNumbers.length; a++) {
final times = (num / arabianRomanNumbers[a]).truncate(); // equals 1 only when arabianRomanNumbers[a] = num
// executes n times where n is the number of times you have to add
// the current roman number value to reach current num.
builder.write(romanNumbers[a] * times);
num -= times * arabianRomanNumbers[a]; // subtract previous roman number value from num
}
return builder.toString();
}
void main() {
for (var i = 0; i <= 1000; i++) {
print('$i => ${intToRoman(i)}');
}
}

ArithGeo(arr) CoderByte Ruby: Why doesn't this solution work for certain test case scenarios

Below I have posted the instructions for this problem along with my solution. A few test case scenarios have failed, but seem to be working for most. Can anybody help out at which point I've gone wrong? Any help is much appreciated!!
Using the Ruby language, have the function ArithGeo(arr) take the array of numbers stored in arr and return the string "Arithmetic" if the sequence follows an arithmetic pattern or return "Geometric" if it follows a geometric pattern.
If the sequence doesn't follow either pattern return -1.
An arithmetic sequence is one where the difference between each of the numbers is consistent
Arithmetic example: [2, 4, 6, 8]
In a geometric sequence, each term after the first is multiplied by some constant or common ratio.
Geometric example: [2, 6, 18, 54]
Negative numbers may be entered as parameters, 0 will not be entered, and no array will contain all the same elements.
Code:
def arithGeo(num)
idx = 0
while idx < num.length
if ((num[idx] - num[idx + 1]) == (num[idx + 1] - num[idx + 2]))
return "Arithmetic"
elsif ((num[idx + 1] / num[idx]) == (num[idx + 2] / num[idx + 1]))
return "Geometric"
else
return "-1"
end
idx += 1
end
end
#Test Cases that Failed
p arithGeo([1, 2, 3, 4, 5, 10, 20])
p arithGeo([1, 2, 3, 4, 5, 6, 7, 88, 2])
p arithGeo([10, 110, 210, 310, 410, 511])
OK, lets do a much more "ruby like" way:
def arith?(arr)
check_arr = []
arr.reverse.inject {|memo, num| check_arr << (memo - num); num}
#loop through from highest to lowest, subtracting each from the next and store in check_arr
check_arr.all? {|num| num == check_arr[-1]}
#check that all results are the same in the arr i.e. [2,2,2,2,2]
end
This returns true if all of the operations return the same result, thus a linear progression.
def geo?(arr)
check_arr = []
arr.reverse.inject {|memo, num| check_arr << (memo / num); num}
#loop through from highest to lowest, dividing each by the next and store in check_arr
check_arr.all? {|x| x == check_arr[-1]}
#check that all products are the same in the arr i.e. [3,3,3,3,3]
end
This returns true if all of the operations return the same result, thus a geometric progression.
Now use those methods in your other method
def arith_geo?(arr)
if arith?(arr)
'Arithmetic'
elsif geo?(arr)
'Geometric'
else
-1
end
end
You did use a while but you do not loop over the data, because you write return you will only ever look at the first three numbers and then immediately return the result. You will have to keep the previous result, and make sure the result stays the same to return either geometric or arithmetic.
This should help you to complete the exercise :)
I was able to do the solution in JavaScript and this is what I came up with:
function algoGeo(arr){
var algo = true;
var geo = true;
//first check algo
for(var k = 1; k < arr.length; k++){
if( (arr[0] + (arr[1] - arr[0]) * k) !== arr[k] && algo ){
algo = false;
}
if( arr[0] * Math.pow(arr[1] / arr[0], k) !== arr[k] && geo){
geo = false;
}
}
return algo ? "Arithmetic" : geo ? "Geometric" : -1;
}
var arr = [5,12,19,26];
console.log(algoGeo(arr));
def ArithGeo(arr)
diff1 = []
diff2 = []
arr.each_index do |x|
if(x + 1 < arr.length)
diff1 << arr[x + 1] - arr[x]
diff2 << arr[x + 1] / arr[x]
end
end
diff1.uniq.size == 1 ? "Arithmetic" : diff2.uniq.size == 1 ? "Geometric" : -1
end
A little late but this is what i came up with when trying to solve this same question.

rewriting of Z3_ast during its traversing in C++

to_expr function leads to error. Could you advise what is wrong below?
context z3_cont;
expr x = z3_cont.int_const("x");
expr y = z3_cont.int_const("y");
expr ge = ((y==3) && (x==2));
ge = swap_tree( ge );
where swap_tree is a function that shall swap all operands of binary operations. It defined as follows.
expr swap_tree( expr e ) {
Z3_ast ee[2];
if ( e.is_app() && e.num_args() == 2) {
for ( int i = 0; i < 2; ++i ) {
ee[ 1 - i ] = swap_tree( e.arg(i) );
}
for ( int i = 0; i < 2; ++i ) {
cout <<" ee[" << i << "] : " << to_expr( z3_cont, ee[ i ] ) << endl;
}
return to_expr( z3_cont, Z3_update_term( z3_cont, e, 2, ee ) );
}
else
return e;
}
The problem is "referencing counting". A Z3 object can be garbage collected by the system if its reference counter is 0. The Z3 C++ API provides "smart pointers" (expr, sort, ...) for automatically managing the reference counters for us. Your code uses Z3_ast ee[2]. In the for-loop, you store the result of swap_tree(e.arg(0)) into ee[0]. Since the reference counter is not incremented, this Z3 object may be deleted when executing the second iteration of the loop.
Here is a possible fix:
expr swap_tree( expr e ) {
if ( e.is_app() && e.num_args() == 2) {
// using smart-pointers to store the intermediate results.
expr ee0(z3_cont), ee1(z3_cont);
ee0 = swap_tree( e.arg(0) );
ee1 = swap_tree( e.arg(1) );
Z3_ast ee[2] = { ee1, ee0 };
return to_expr( z3_cont, Z3_update_term( z3_cont, e, 2, ee ) );
}
else {
return e;
}
}

Resources