Related
I'm new to Dart. I was trying to convert integer to roman. But It returns nothing. Can you guys help me? here is my code sample.
this code is from the Leetcode problem section.
class Solution {
String intToRoman(int num) {
List<int> numbers = [1,4,5,9,10,40,50,90,100,400,500,900,1000];
List<String> romans = ["I","IV","V","IX","X","XL","L","XC","C","CD","D","CM", "M"];
int index = romans.length - 1;
String roman = '';
for(num >0;numbers[index]<=num;){
roman += romans[index];
num -= numbers[index];
index -= 1;
}
return roman;
}
}
just change a little bit on the logic
.try on dartpad: https://dartpad.dev/?id
void main() {
print (intToRoman(30)); // result: XXX
}
String intToRoman(int num) {
List<int> numbers = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
List<String> romans = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"];
String roman = '';
for (int i = 0; i < numbers.length; i++) {
while (num >= numbers[i]) {
roman += romans[i];
num -= numbers[i];
}
}
return roman;
}
This solution is based on Wiki:
class Solution {
/// digit: 3=Thousands(10³), 2=Hundreds(10²), 1=Tens(10), 0=Units(1)
/// Range for roman numerals: 1...3999
static final romanNumerals = <int,Map<int,String>>{
1 : {3:'M', 2:'C', 1:'X', 0:'I'},
2 : {3:'MM', 2:'CC', 1:'XX', 0:'II'},
3 : {3:'MMM', 2:'CCC', 1:'XXX', 0:'III'},
4 : {2:'CD', 1:'XL', 0:'IV'},
5 : {2:'D', 1:'L', 0:'V'},
6 : {2:'DC', 1:'LX', 0:'VI'},
7 : {2:'DCC', 1:'LXX', 0:'VII'},
8 : {2:'DCCC', 1:'LXXX', 0:'VIII'},
9 : {2:'CM', 1:'XC', 0:'IX'},
};
/* ---------------------------------------------------------------------------- */
Solution();
/* ---------------------------------------------------------------------------- */
String intToRoman(int number) {
if (number < 1 || number >= 4000) return '';
var list = number.toString().split('').map(int.parse).toList();
var buffer = StringBuffer();
final len = list.length;
for (var i = 0; i < len; i++) {
var digit = list[i];
if (digit == 0) continue;
buffer.write(romanNumerals[digit]![len - 1 - i]);
}
return buffer.toString();
}
/* ---------------------------------------------------------------------------- */
void intToRoman2(int number) {
print(intToRoman(number));
}
}
void main(List<String> args) {
Solution()
..intToRoman2(3)
..intToRoman2(58)
..intToRoman2(1994)
;
}
Output:
III
LVIII
MCMXCIV
This code was already sent to LeetCode with the following results:
Runtime: 1130 ms, faster than 27.96% of Dart online submissions for Integer to Roman.
Memory Usage: 150.5 MB, less than 44.09% of Dart online submissions for Integer to Roman.
why not use the simple way?
I use this extension to convert english numbers to persian numbers
extension StringExtensions on String {
String persianNumber() {
String number = this;
number = number.replaceAll("1", "۱");
number = number.replaceAll("2", "۲");
number = number.replaceAll("3", "۳");
number = number.replaceAll("4", "۴");
number = number.replaceAll("5", "۵");
number = number.replaceAll("6", "۶");
number = number.replaceAll("7", "۷");
number = number.replaceAll("8", "۸");
number = number.replaceAll("9", "۹");
number = number.replaceAll("0", "۰");
return number;
}
}
extension IntExtensions on int {
String persianNumber() {
String number = this.toString();
number = number.replaceAll("1", "۱");
number = number.replaceAll("2", "۲");
number = number.replaceAll("3", "۳");
number = number.replaceAll("4", "۴");
number = number.replaceAll("5", "۵");
number = number.replaceAll("6", "۶");
number = number.replaceAll("7", "۷");
number = number.replaceAll("8", "۸");
number = number.replaceAll("9", "۹");
number = number.replaceAll("0", "۰");
return number;
}
}
I try to resolve the highest value of a Map, with different field names. In this case highestValue should be "Luke"
String? highestValue;
Map<Object?, Object?>? points =
{
"Vader": 40,
"Obi-Wan": 20,
"Luke": 50,
};
highestValue = ...
thanks
Your map is terribly typed so I am not sure what situations we need to take into account here. E.g. what should happen if the value are not an int? But I have made the following example of how you could do it:
void main() {
String? highestValue;
Map<Object?, Object?>? points =
{
"Vader": 40,
"Obi-Wan": 20,
"Luke": 50,
};
highestValue = points.entries.reduce((a, b) {
final aValue = a.value;
final bValue = b.value;
if (aValue is! int) {
return b;
}
if (bValue is! int) {
return a;
}
return aValue > bValue ? a : b;
}).key as String?;
print(highestValue); // Luke
}
But as you can see, a lot of the logic comes from the fact that your map contains Object? objects and not a more specific type like int.
Extra solution added after request in comment
If we want to have extract the second biggest, we are starting to get into the territory where it makes more sense to just generate a list and then order it.
So we can do something like this where we do this based on the map:
void main() {
String? highestValue;
Map<Object?, Object?>? points = {
"Vader": 40,
"Obi-Wan": 20,
"Obi-Wan": 20,
"Luke": 50,
};
final sortedEntries = points.entries.toList()
..sort((entry1, entry2) {
final aValue = entry1.value;
final bValue = entry2.value;
if (aValue is! int) {
return 1;
}
if (bValue is! int) {
return -1;
}
return bValue.compareTo(aValue);
});
sortedEntries
.forEach((entry) => print('Key: ${entry.key} | Value: ${entry.value}'));
// Key: Luke | Value: 50
// Key: Vader | Value: 40
// Key: Obi-Wan | Value: 20
String nameOfTheSecondLargest = sortedEntries[1].key as String;
print(nameOfTheSecondLargest); // Vader
}
Map<String, int>? points =
{
"Vader": 40,
"Obi-Wan": 20,
"Luke": 50,
};
String highest = points.keys.first;
int max = points.values.first;
points.forEach((key, value) {
if(max < value){
max=value;
highest = key;
}
});
You can do something like this. More easy to understand.
Simplest way to do this :
import:
import 'dart:math';
then
Map<Object?, Object?> points = {
"Vader": 40,
"Obi-Wan": 20,
"Luke": 50,
};
var highestValue = (points.values.toList().map((e) => e as int).reduce(max));
print(highestValue);
I have 5 arrays inside an array,
let arrays = [[1,2,3], [1,2,3,4], [4,5,6,7], [21, 34, 89], [555, 34]]
Now, I want to group them if they have atleast 1 similar element.
Expected output.
[[1,2,3,4,5,6,7], [21, 34, 89, 555]]
Since array 1, 2 and 3 has similar element, they will combine. And array 4 and 5 has similar element so they will be combined as well.
var finalSimilarArray = [[String]]()
let similararray = [[1,2,3,4,5,6,7], [21, 34, 89, 555]]
similarArray.forEach { array in
similarArray.enumerated().forEach { index, array2 in
if !Set(array2).intersection(Set(array)).isEmpty {
finalSimilarArray.append(contentsOf: [array] + [array2])
similarArray.remove(at: index)
}
}
}
I tried to looping and conditions with no luck, not even close. to the real deal.
Thank you, I hope I explained it clearly. :D
My 2 cent: Start with a function which merges a single array into a list of (mutually disjoint) arrays:
func mergeOne<T>(array: [T], into merged: [[T]]) -> [[T]]
where T: Hashable & Comparable
{
var set = Set(array)
var result = merged.compactMap { m -> [T]? in
if set.isDisjoint(with: m) {
return m
} else {
set.formUnion(m)
return nil
}
}
result.append(set.sorted()) // Or: result.append(Array(set))
return result
}
The array is converted to a set so that overlapping tests with another array and joining the elements can be done efficiently. This requires the elements to conform to the Hashable protocol. The Comparable conformance is only needed to sort the merged arrays – if that is not needed then this constraint can be removed.
The above function compares the given array with each element of the list, and joins them if there is an overlap. The important point is to use the new enlarged array (actually: set) for the subsequent comparisons. So arrays with no overlap with the new array are kept in the list, and the others are joined to a new array which is then appended to the list.
With that utility function we can merge a given list of arrays easily:
func merge<T>(arrays: [[T]]) -> [[T]]
where T: Hashable & Comparable
{
return arrays.reduce(into: [], { $0 = mergeOne(array: $1, into: $0) })
}
Starting with an empty list, the array elements are merged repeatedly.
Examples:
print(merge(arrays: [[1, 2, 3], [1, 2, 3, 4], [4, 5, 6, 7], [21, 34, 89], [555, 34]]))
// [[1, 2, 3, 4, 5, 6, 7], [21, 34, 89, 555]]
print(merge(arrays: [[1,2], [3, 4], [5, 6], [3, 5], [6, 2]]))
// [[1, 2, 3, 4, 5, 6]]
Compare each array element to every other array element to see if there is any overlap. If there is, then combine the arrays into a partial result. Next compare the partial result to each element in the results. If there is any overlap, then combine then. If not, then append the partial result to the array of results.
extension Collection where Element: Hashable {
func unique() -> [Element] {
return Array(Set(self))
}
}
extension Collection where Element: Equatable {
func containsAny(of other: Self) -> Bool {
for element in other {
if contains(element) {
return true
}
}
return false
}
}
func merge(arrays: [[Int]]) -> [[Int]] {
return arrays.reduce(into: Array<[Int]>(), { results, slice1 in
var partial = slice1
for slice2 in arrays {
if slice2.containsAny(of: partial) {
partial.append(contentsOf: slice2)
}
}
if let index = results.firstIndex(where: { $0.containsAny(of: partial) }) {
results[index] = (results[index] + partial).unique().sorted()
} else {
results.append(partial.unique().sorted())
}
})
}
print(merge(arrays: [[1,2,3], [1,2,3,4], [4,5,6,7], [21, 34, 89], [555, 34]]))
print(merge(arrays: [[1,2], [3, 4], [1, 3]]))
Results are:
[[1, 2, 3, 4, 5, 6, 7], [21, 34, 89, 555]]
[[1, 2, 3, 4]]
You can use a Set which guarantees unique values, when using .union which merges the values of two sets into one.
let givenArray: [Set<Int>] = [[1,2,3], [1,2,3,4], [4,5,6,7], [21, 34, 89], [555, 34]]
let expectedArray: [Set<Int>] = [[1,2,3,4,5,6,7], [21, 34, 89, 555]]
let groupedArray: [Set<Int>] = givenArray.reduce([]) { (result, numbers) -> [Set<Int>] in
var mutableResult = result
if let indexOfNumbersToMergeWith = mutableResult.firstIndex(where: { (set) -> Bool in
!set.isDisjoint(with: numbers) // Returns: `true` if the set has no elements in common with `other`
}) {
mutableResult[indexOfNumbersToMergeWith] = mutableResult[indexOfNumbersToMergeWith].union(numbers)
} else {
mutableResult.append(numbers)
}
return mutableResult
}
print(groupedArray == expectedArray) // prints: true
EDIT:
I've updated the answer to support the following given array [[1,2], [3,4], [1,3]]
let givenArray: [Set<Int>] = [[1,2], [3,4], [1,3]]
let expectedArray: [Set<Int>] = [[1,2,3,4]]
let groupedArray: [Set<Int>] = givenArray.reduce([]) { (result, numbers) -> [Set<Int>] in
var mutableResult = result
let indexesOfNumbersToMergeWith: [Int] = mutableResult.enumerated().reduce([], { (result, arguments) -> [Int] in
var mutableResult = result
let (index, numbersToCompare) = arguments
// Returns: `true` if the set has no elements in common with `other`
if !numbersToCompare.isDisjoint(with: numbers) {
mutableResult.append(index)
}
return mutableResult
})
if !indexesOfNumbersToMergeWith.isEmpty {
// Note that I've sorted the indexes in descending order. This is because everytime you remove an element, the indexes of the elements beyond is reduce by one.
let numbersToMergeWith = indexesOfNumbersToMergeWith.sorted(by: { $1 < $0 }).map { (index) -> Set<Int> in
return mutableResult.remove(at: index) // removes and returns number set
}
mutableResult.append(numbersToMergeWith.reduce(into: numbers, { $0 = $0.union($1) }))
} else {
mutableResult.append(numbers)
}
return mutableResult
}
print(groupedArray == expectedArray) // prints: true
I have one simple array like:
var cellOrder = [1,2,3,4]
I want to exchange elements like suppose a second element with first element.
And result will be:
[2,1,3,4]
I know we can use exchangeObjectAtIndex with NSMutableArray But I want to use swift array. Any ways to do same with swift [Int] array?
Use swap:
var cellOrder = [1,2,3,4]
swap(&cellOrder[0], &cellOrder[1])
Alternately, you can just assign it as a tuple:
(cellOrder[0], cellOrder[1]) = (cellOrder[1], cellOrder[0])
Swift 4
swapAt(_:_:):
cellOrder.swapAt(index0, index1)
One option is:
cellOrder[0...1] = [cellOrder[1], cellOrder[0]]
Details
Xcode Version 10.3 (10G8), Swift 5
Base (unsafe but fast) variant
unsafe - means that you can catch fatal error when you will try to make a swap using wrong (out of the range) index of the element in array
var array = [1,2,3,4]
// way 1
(array[0],array[1]) = (array[1],array[0])
// way 2
array.swapAt(2, 3)
print(array)
Solution of safe swap
save swap attempt (checking indexes)
possible to know what index wrong
do not use this solution when you have to swap a lot of elements in the loop. This solution validates both (i,j) indexes (add some extra logic) in the swap functions which will make your code slower than usage of standard arr.swapAt(i,j). It is perfect for single swaps or for small array. But, if you will decide to use standard arr.swapAt(i,j) you will have to check indexes manually or to be sure that indexes are not out of the range.
import Foundation
enum SwapError: Error {
case wrongFirstIndex
case wrongSecondIndex
}
extension Array {
mutating func detailedSafeSwapAt(_ i: Int, _ j: Int) throws {
if !(0..<count ~= i) { throw SwapError.wrongFirstIndex }
if !(0..<count ~= j) { throw SwapError.wrongSecondIndex }
swapAt(i, j)
}
#discardableResult mutating func safeSwapAt(_ i: Int, _ j: Int) -> Bool {
do {
try detailedSafeSwapAt(i, j)
return true
} catch {
return false
}
}
}
Usage of safe swap
result = arr.safeSwapAt(5, 2)
//or
if arr.safeSwapAt(5, 2) {
//Success
} else {
//Fail
}
//or
arr.safeSwapAt(4, 8)
//or
do {
try arr.detailedSafeSwapAt(4, 8)
} catch let error as SwapError {
switch error {
case .wrongFirstIndex: print("Error 1")
case .wrongSecondIndex: print("Error 2")
}
}
Full sample of safe swap
var arr = [10,20,30,40,50]
print("Original array: \(arr)")
print("\nSample 1 (with returning Bool = true): ")
var result = arr.safeSwapAt(1, 2)
print("Result: " + (result ? "Success" : "Fail"))
print("Array: \(arr)")
print("\nSample 2 (with returning Bool = false):")
result = arr.safeSwapAt(5, 2)
print("Result: " + (result ? "Success" : "Fail"))
print("Array: \(arr)")
print("\nSample 3 (without returning value):")
arr.safeSwapAt(4, 8)
print("Array: \(arr)")
print("\nSample 4 (with catching error):")
do {
try arr.detailedSafeSwapAt(4, 8)
} catch let error as SwapError {
switch error {
case .wrongFirstIndex: print("Error 1")
case .wrongSecondIndex: print("Error 2")
}
}
print("Array: \(arr)")
print("\nSample 5 (with catching error):")
do {
try arr.detailedSafeSwapAt(7, 1)
} catch let error as SwapError {
print(error)
}
print("Array: \(arr)")
Full sample log of safe swap
Original array: [10, 20, 30, 40, 50]
Sample 1 (with returning Bool = true):
Result: Success
Array: [10, 30, 20, 40, 50]
Sample 2 (with returning Bool = false):
Result: Fail
Array: [10, 30, 20, 40, 50]
Sample 3 (without returning value):
Array: [10, 30, 20, 40, 50]
Sample 4 (with catching error):
Error 2
Array: [10, 30, 20, 40, 50]
Sample 5 (with catching error):
wrongFirstIndex
Array: [10, 30, 20, 40, 50]
Use swapAt method,
var arr = [10,20,30,40,50]
arr.swapAt(2, 3)
Use the index to swap element.
I am trying to put fibonacci number in an array and wanted to see the array output in playground console but for some reason I do not see any ouput. Can someone plz help in making me understand the mistake that I am cdoing in my program ?
import UIKit
class FibonacciSequence {
let includesZero: Bool
let values: [Int]
init(maxNumber: Int, includesZero: Bool) {
self.includesZero = includesZero
values = [0]
var counter: Int
if (includesZero == true) { counter = 0 }
else { counter = 1 }
for counter <= maxNumber; {
if ( counter == 0 ) {
values.append(0)
counter = 1
}
else {
counter = counter + counter
values.append(counter)
}
}
println(values)
}
println(values)
return values
}
let fibanocciSequence = FibonacciSequence(maxNumber:123, includesZero: true)
#ABakerSmith has given you a good rundown of the problems in the code as-is, but you also might want to consider, instead of a class that initializes an array member variable, writing a SequenceType that returns fibonacci numbers:
struct FibonacciSequence: SequenceType {
let maxNumber: Int
let includesZero: Bool
func generate() -> GeneratorOf<Int> {
var (i, j) = includesZero ? (0,1) : (1,1)
return GeneratorOf {
(i, j) = (j, i+j)
return (i < self.maxNumber) ? i : nil
}
}
}
let seq = FibonacciSequence(maxNumber: 20, includesZero: false)
// no arrays were harmed in the generation of this for loop
for num in seq {
println(num)
}
// if you want it in array form:
let array = Array(seq)
You could of course memoize the sequence if you want to improve performance on multiple generations.
Your problem is your code has errors in it; if there are errors in your code Playgrounds won't run it and you won't get any output.
On the line for counter <= maxNumber; you've got a semi-colon, but also, I'm pretty sure you can't declare a for loop like that, unless I'm missing something? You could use a while loop though.
Why are you trying to return values from your init method?
You've declared values as a constant but are then trying to change it using append.
Using this code and fixing the errors stated does not produce the Fibonacci sequence, instead it produces: [0, 0, 2, 4, 8, 16, 32, 64, 128]
Try this code:
class FibonacciSequence {
let values: [Int]
init(maxNumber: Int, includesZero: Bool) {
var tempValues = includesZero ? [0] : [1]
var current = 1
do {
tempValues.append(current)
let nMinus2 = tempValues[tempValues.count - 2]
let nMinus1 = tempValues[tempValues.count - 1]
current = nMinus2 + nMinus1
} while current <= maxNumber
self.values = tempValues
}
}
Then create an instance:
let fibanocciSequence = FibonacciSequence(maxNumber:123, includesZero: true)
println(fibanocciSequence.values) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Hope that helps!