Flutter & Dart Coding Challenge #1 - In Reverse
Build your Dart and Flutter Prowess with our first Dart/Flutter coding challenge!
Welcome to the Dart Coding Challenge Series Video #1! If you're looking for ways to improve your coding skills, then you've come to the right place. The key to getting better at coding is to practice, practice, practice. And what better way to do that than with coding challenges?
In this series, we'll present you with a series of problems that will escalate in both difficulty and fun. We'll describe the problem and the criteria for solving it, and then we'll ask you to pause the video and complete the challenge entirely on your own. You're free to attempt to solve it in any way you see fit.
After you've given it a shot, we'll give you a few hints on how to solve it without demonstrating our solution. Then, we'll give you another opportunity to solve it. Finally, we'll show you how we solved it. Keep in mind that there's always more than one way to solve a problem, so be creative, as long as you do it within the parameters laid out! Then, share the details of your solution in the comments using any means you see fit.
For our first problem, we're going to start with something rather simple. It will require a bit of thought, but overall, it should be pretty easy. Here are the specifications of the problem:
Create an application that does the following:
Use the Dart Create function to create this project for you.
Asks the user, through the command-line terminal, to enter a random sequence of numbers.
There must be more than 6 numbers and less than 50 numbers.
Using any coding method that you see fit, your job is to reverse the order of the numbers so that the last number is the first and the first number is the last. For example, 13371337 becomes 73317331.
Then display the number back to the user in the command line.
If the user inputs a number with less than 6 digits prompt them again with a custom message.
If the user inputs a number with less than 50 digits prompt them again with another number.
If the user enters a non-numeric character, prompt them again with another message.
Use individual functions to execute this application where appropriate.
Hints
Need a Hint? Here you go! Only use one hint at a time; complete the challenge with as little help as possible:
Dart has a library called dart:io. Try importing it and looking at functionality called stdin.readLineSync() and stdout.write().
The do-while loop can be a great way to re-execute prompts for input until the proper criteria are met.
The for or forEach loop might be a wonderful way to traverse through a String. Remember, you can access each letter in a String by using brackets, as if it were a List or array. Example String[1] would be the second letter (remember the first is zero).
The purpose of these challenges is to flex your mental muscle, so no ChatGPT or other tools are allowed. Practice, practice, practice, and have fun!
Solution #1
For both solutions we used the dart create command to setup our project.
dart create challenge_1
This creates a file and folder structure that contains folders called /bin, /lib and /test.
In a default Dart project, the /bin
directory is where you can place executable scripts that can be run directly from the command line. The /lib
directory is where you can store the Dart source code files that will be used to build your application or package. The /test
directory is where you can place your test files, which are used to test your code and ensure that it works as expected. These directories are essential for organizing your code and making it more maintainable.
/bin file
import 'package:dart_coding_challenges/dart_coding_challenges.dart' as dart_coding_challenges;
/* Dart Coding Challenge #1
Create an application that Does the following:
- Use the Dart Create function to create this project for you.
- Asks the user, through the command-line terminal, to enter a random sequence of numbers.
- There must be more than 6 numbers and less than 50 numbers.
- Then, using any coding method that you see fit, your job is to reverse the order of the numbers so that the last number is the first and the first number is the last. For example, 13371337 becomes 73317331.
- Then display the number back to the user in the command line.
*/
void main(List<String> arguments) {
//Get a String that contains integers only from the command line.
String number = dart_coding_challenges.getNumberFromCommandLine();
//Reverse the order of the numbers in the String.
String reverseNumber = dart_coding_challenges.reverseOrderOfCharactersInString(number);
//Print the reversed number to the user with a message.
print("Here is your number $number reversed: $reverseNumber!");
}
This is our main executable file. Notes of project specifications were included as a reference. The main function is simple as it is mostly referencing files from the /lib folder.
This code is using three functions, namely getNumberFromCommandLine
, reverseOrderOfCharactersInString
, and print
. The purpose of getNumberFromCommandLine
is to retrieve a string of integers from the command line. The purpose of reverseOrderOfCharactersInString
is to take the input string of integers and reverse the order of the characters in the string. Finally, the purpose of print
is to display a message to the user on the console, which in this case includes the original number and its reversed form. Overall, the code takes a user-inputted string of integers, reverses the order of the characters in that string, and then displays the original and reversed forms of the string back to the user.
/lib file
import 'dart:io';
/* Get a number from the command line. We chose String
so that it is easier to manipulate and reverse! */
String getNumberFromCommandLine() {
String number;
stdout.write("Input a number (integer) with between 5 and 50 digits: ");
//Loop repeatedly to ask for user input until our conditions are met.
do {
number = stdin.readLineSync()!;
if (number.length < 6) {
stdout.write("Error! Please enter 6 or more numbers: ");
} else if (number.length > 50) {
stdout.write("Error! Please enter less than 50 numbers: ");
} else if (!isNumeric(number)) {
stdout.write("Error! Please enter only integers: ");
}
} while (number.isEmpty || (number.length < 6 || number.length > 50) || !isNumeric(number));
return number;
}
//Check for numeric strings only.
bool isNumeric(String str) {
return RegExp(r'^\d+$').hasMatch(str);
}
//Let's take our String and reverse the order!
String reverseOrderOfCharactersInString(String str) {
String buffer = "";
//Loop through each character in the String 1 by 1 in reverse order.
for (int i = str.length; i > 0; i--) {
//Write the reversed String to our buffer.
buffer += str[i - 1];
}
return buffer;
}
getNumberFromCommandLine()
The first function is called getNumberFromCommandLine()
and is responsible for getting a number input from the user via the command line. The function prompts the user to enter a number between 6 and 50 digits long, and then checks if the input meets the specified conditions which in this case means it is also numeric. The function uses a do-while loop to repeat the prompt until the user provides a valid input. Notice that we are using stdout.write instead of print since the added line breaks from print are unwanted. The input is returned as a string.
isNumeric(String str)
The second function is called isNumeric(String str)
and checks if a given string consists of only numeric characters. It returns a boolean value true
if the string contains only numeric characters and false
otherwise. Notice the user of the regular expression!
What is a Regular Expression?
A Regular Expression, also known as RegEx, is a sequence of characters that define a search pattern. In this code, the RegExp
object is being used to create a RegEx pattern that matches strings with only digits (0-9). The r
before the string tells Dart that it's a raw string, so special characters don't need to be escaped. The ^
and $
characters specify the start and end of the string, respectively. The +
character means that the pattern must match one or more digits in a row. The hasMatch()
method then checks if the RegEx pattern matches the input string, and returns a boolean value of true
if it does, or false
otherwise.
reverseOrderOfCharactersInString()
The third function is called reverseOrderOfCharactersInString(
and takes a string as input. The function then reverses the order of the characters in the input string using a for loop and returns the reversed string. The function uses a for loop to iterate through each character in the string in reverse order and writes the reversed string to a buffer and then returns the buffer as a string. Notice that the for loop looks a bit wonky, because it is starting at the last character in the String and traversing backward in order to add characters to the buffer in the proper order.
Overall, these functions work together to get a number input from the user, check if it is valid, and then reverse the order of the digits in the number.
/test file
import 'package:dart_coding_challenges/dart_coding_challenges.dart';
import 'package:test/test.dart';
void main() {
test('isNumeric', () {
expect(isNumeric("asdfsdf"), false);
expect(isNumeric("12356456"), true);
});
test('reverseNumber', () {
expect(reverseOrderOfCharactersInString("123"), "321");
expect(reverseOrderOfCharactersInString("123456789"), "987654321");
});
}
The final file contains unit tests to make sure the code works. isNumeric looks at our isNumeric function and analyzes several common inputs and looks for the expected output. the reverseNumber test does the same thing but ensures that the Strings are being properly reversed. The dart test
command can be used to conduct the unit tests and see results.
Solution 2
The first solution focused on a traditional approach to this problem, without leveraging inbuilt DART functionality. This time we will look at an approach that is more DART centric. We have the same file structure as the problem above. In fact, the /bin file is identical, as is the /test file. The only changes come inside the /bin file, particularly in the reverseOrderOfCharactersInString()
function.
String reverseOrderOfCharactersInString(String str) {
//Create a list so we can use the list manipulation tools.
final list = str.trim().split('').map(int.parse).toList();
//Reverse our list using the built in list reverse function.
final reversed = list.reversed.toList();
//Return our list in String format. .Join accomplishes this while stripping the brackets from our list.
return reversed.join('');
}
Notice that we are creating a list using a rather cryptic sequence of method chaining. Here is what is happening:
The input to the function is a string
str
, which is the string that we want to reverse.First, the string is trimmed using the
trim()
method, which removes any whitespace characters at the beginning or end of the string.Then, the string is converted to a list of integers using the
split()
method, which splits the string into a list of individual characters and themap()
method, which maps each character in the list to its corresponding integer value using theint.parse()
function.Next, the
reversed
method is called on the list, which returns a new list containing the elements of the original list in reverse order.Finally, the
join()
method is called on the reversed list to convert it back to a string, and the resulting string is returned from the function.
So, in summary, the function takes a string, converts it to a list of integers, reverses the list, and then joins the elements of the reversed list back into a string, effectively reversing the original string.
Considerations
How did your solution match up with the two presented here? Remember, there is no “right” or “wrong” answer so long as the program functions. I’d love to see a link to your solution in the comments!
Think about the two solutions presented above as well. Which one do you prefer? The standard solution that would make more sense to a traditional programmer, or the very DART-centric approach of our second solution. Why do you feel the way you do?
Stay tuned for more Dart & Flutter coding challenges!