Tried writing a sort method where input was given like a string of comma-delimited years and year ranges String input = '2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013';
Expectation is to get a string of comma-delimited years and year ranges,and remove all duplicates and invalid inputs.
Below is class written which is not giving me correct output
public class sortYearAndYearRangesString {
public static List<String> sortSpecialString(String input) {
system.debug(input);
List<String> inputList = input.split('');
system.debug(inputList);
Map<Integer,String> stringMap = new Map<Integer,String>();
system.debug(stringMap);
List<String> output = new List<String>();
for (Integer i=0; i<inputList.size(); i++) {
String charac = inputList[i];
if(!charac.isAlphaNumeric()) {
system.debug(charac);
stringMap.put(i,charac);
}else {
output.add(charac);
system.debug(output);
}
}
String finalString = String.join(output,'');
system.debug(finalString);
List<String> resultList = finalString.reverse().split('');
for( Integer I : stringMap.keySet() ){
system.debug(I);
resultList.add(I,stringMap.get(I));
system.debug(resultList);
}
return resultList;
}
Tried validating the solution in Anonymous Apex but no success
public static void validateSolution() {
String input = '2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013';
List<Integer> expected = new List<Integer> {2013,2017,2018,2020,2021,2022,2023,2025};
List<Integer> actual = sortYearAndYearRangesString(input);
System.assertEquals(expected, actual, 'Invalid Results');
}
}
Your help is appreciated
Regards
Carolyn
According to your test case, you should also define at least a constant for a maximum value, in order to exclude 20261. Probably you need a minimum too.
I used 1700 as min and 4000 as max because these are the limits for a Date or Datatime field: docs
Moreover the method must return a List<Integer> instead of a List<String>.
You don't need a Map, just a Set would work.
public class SortYearAndYearRangesString {
private static final Integer MAX_YEAR = 4000;
private static final Integer MIN_YEAR = 1700;
public static List<Integer> sortSpecialString(String input) {
Set<Integer> output = new Set<Integer>();
List<String> yearsList = input.split(',');
for (String yearString : yearsList) {
yearString = yearString.trim();
if (yearString.isNumeric()) {
try {
Integer year = Integer.valueOf(yearString);
if (year >= MIN_YEAR && year <= MAX_YEAR) {
output.add(year);
}
} catch (TypeException e) {
System.debug(e.getMessage());
}
} else {
List<String> range = yearString.split('-');
if (range.size() == 2 && range[0].isNumeric() && range[1].isNumeric()) {
try {
// Modify the following two lines once you know how to handle range like 1300-1500 or 3950-4150
Integer firstYear = Math.max(Integer.valueOf(range[0]), MIN_YEAR);
Integer lastYear = Math.min(Integer.valueOf(range[1]), MAX_YEAR);
while (firstYear <= lastYear) {
output.add(firstYear++);
}
} catch (TypeException e) {
System.debug(e.getMessage());
}
}
}
}
List<Integer> sortedYears = new List<Integer>(output);
sortedYears.sort();
return sortedYears;
}
}
If a range that exceed the boundaries (like 1300-1500 or 3950-4150) should be treated as invalid and skipped, please change these lines
Integer firstYear = Math.max(Integer.valueOf(range[0]), MIN_YEAR);
Integer lastYear = Math.min(Integer.valueOf(range[1]), MAX_YEAR);
while (firstYear <= lastYear) {
output.add(firstYear++);
}
as follow:
Integer firstYear = Integer.valueOf(range[0]);
Integer lastYear = Integer.valueOf(range[1]);
if (firstYear >= MIN_YEAR && lastYear <= MAX_YEAR) {
while (firstYear <= lastYear) {
output.add(firstYear++);
}
}
I tested it in anonymous console with the following code:
String input = '2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013';
List<Integer> expected = new List<Integer> {2013,2017,2018,2020,2021,2022,2023,2025};
List<Integer> actual = SortYearAndYearRangesString.sortSpecialString(input);
System.debug(actual);
System.assertEquals(expected, actual, 'Invalid Results');
input = '1500,2017, 2018,2020-2023,1800-1700,2020,20a9,19z5-1990,2025,20261,2013,3998-4002';
expected = new List<Integer> {2013,2017,2018,2020,2021,2022,2023,2025,3998,3999,4000};
actual = SortYearAndYearRangesString.sortSpecialString(input);
System.assertEquals(expected, actual, 'Invalid Results');
I made some changes to the class.
It does increment all ranges - and doesn't check if they're years that would make sense. You'll need to add that logic in there (e.g. 1500-1600 would return all years between 1500-1600. Prob best to cap at 1900 or something)
public class SortYearAndYearRangesString{
public static List<Integer> sortSpecialString(String input){
List<String> inputList = input.split(',');
Set<Integer> output = new Set<Integer>();
system.debug('input ' + input);
system.debug('inputList ' + inputList);
for (String s : inputList){
Set<Integer> tempSet = new Set<Integer>();
s.remove(' ');
if (s.contains('-')){
//// break the ranges and fill in years
List<String> tempSet2 = s.split('-');
for (String s2 : tempSet2){
try{
///capture valid integers
Integer tempInt = Integer.valueOf(s2);
tempSet.add(tempInt);
} catch (Exception e){
tempSet.clear();
break;
}
}
System.debug('set ' + tempSet);
if (tempSet.size() > 1){
List<Integer> tempList = new List<Integer>(tempSet);
tempList.sort ();
Integer r = tempList.size() - 1;
// iterate through the years
for (Integer i = tempList.get(0); i < tempList.get(r); i++){
tempSet.add(i) ;
}
}
} else{
try{
///capture valid integers
Integer tempInt = Integer.valueOf(s);
tempSet.add(tempInt);
} catch (Exception e){
continue;
}
}
output.addAll(tempSet);
}
// output is currently set of ints, need to convert to list of integer
List<Integer> finalOutput = new List<Integer>(output);
finalOutput.sort ();
System.debug('finalOutput :' + finalOutput);
return finalOutput;
}}
All right, so I have this program based where I want to print a receipt from a dentists office. As it is right now, you enter a number and the cost will print accordingly. However, I would like to able to enter multiple numbers in the program and when I type "-1" I want the program to stop and print the total cost. Take a look:
import java.util.Scanner;
public class DentistReception{
public static void main(String[] args) {
double cost = 0;
int treatment = 0;
final double checkUp = 60.00;
final double cleaning = 30.00;
final double cavity = 150.00;
Scanner input = new Scanner(System.in);
System.out.println("What service(s) will be done?: ");
System.out.println("Checkup: 1");
System.out.println("Cleaning: 2");
System.out.println("Cavity: 3");
System.out.println("Exit: -1");
treatment = input.nextInt();
{
if (treatment == 1) {
cost = cost + checkUp;
}
else {
if (treatment == 2) {
cost = cost + cleaning;
}
else {
if (treatment == 3) {
cost = cost + cavity;
}
else {
while (treatment < 0) break;
}
}
}
}
System.out.println("Total cost it:"+cost);
}
}
I want it to loop until i enter "-1", but the break doesn't seem like it wants to. Whenever I put the while or break somewhere else I get the message "break without loop" or something like that.
Use while and capture the option with a boolean variable
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
double cost = 0;
int treatment = 0;
final double checkUp = 60.00;
final double cleaning = 30.00;
final double cavity = 150.00;
boolean repeat = true;
while (repeat) {
Scanner input = new Scanner(System.in);
System.out.println("What service(s) will be done?: ");
System.out.println("Checkup: 1");
System.out.println("Cleaning: 2");
System.out.println("Cavity: 3");
System.out.println("Exit: -1");
treatment = input.nextInt();
input.nextLine();
switch (treatment) {
case 1:
cost = cost + checkUp;
break;
case 2:
cost = cost + cleaning;
break;
case 3:
cost = cost + cavity;
break;
default:
System.out.println("do you want to break out the loop?");
String ans = input.nextLine();
if (ans.equals("y")){
System.out.println("exiting...");
repeat = false;
}
break;
}
// if (treatment == 1) {
// cost = cost + checkUp;
// } else {
// if (treatment == 2) {
// cost = cost + cleaning;
// } else {
// if (treatment == 3) {
// cost = cost + cavity;
// } else {
// while (treatment < 0)
// break;
// }
// }
// }
}
System.out.println("Total cost it:" + cost);
}
}
This question already has answers here:
Sort on a string that may contain a number
(24 answers)
Closed 3 years ago.
The output of this string should be sorted as follows.
The output of this string should be sorted as follows.
public static void main(String[] args) {
String input="";
List<String> items = Arrays.asList(input.split("\\s*,\\s*"));
System.out.println("items: " + items);
Collections.sort(items, new Comparator<String>() {
public int compare(String o1, String o2) {
String o1StringPart = o1.replaceAll("\\d", "");
String o2StringPart = o2.replaceAll("\\d", "");
if (o1StringPart.equalsIgnoreCase(o2StringPart)) {
return extractInt(o1) - extractInt(o2);
}
return o1.compareTo(o2);
}
int extractInt(String s) {
String num = s.replaceAll("\\D", "");
// return 0 if no digits found
return num.isEmpty() ? 0 : Integer.parseInt(num);
}
});
for (String s : items) {
System.out.println(s);
}} }
I assume that all the numeric are integer and all the alphabets are A to Z, you can transform those strings which contains / or - into floating points first, then replace all the alphabets to empty strings. Finally, compare their values as Double.
For example, 51/1 will be 51.1 and 571-573B will be 571.573.
Code snippet
public int compare(String o1, String o2) {
String n1 = o1.replace("-", ".").replace("/", ".").replaceAll("[A-Z]", "");
String n2 = o2.replace("-", ".").replace("/", ".").replaceAll("[A-Z]", "");
// This equals above statements
//String n1 = o1.replaceAll("[-/]", ".").replaceAll("[A-Z]", "");
//String n2 = o2.replaceAll("[-/]", ".").replaceAll("[A-Z]", "");
int result = Double.compare(Double.valueOf(n1), Double.valueOf(n2));
return (result == 0) ? o1.compareTo(o2) : result;
}
This is not the most elegant way, but I think it should work!
Use the below snippet code. Firstly, you need to compare the integer part of the string and in case the integer part is equal compare the string part.
import java.io.*;
import java.util.*;
import java.util.regex.*;
/*
* To execute Java, please define "static void main" on a class
* named Solution.
*
* If you need more classes, simply define them inline.
*/
class Solution {
public static void main(String[] args) {
String input = "605,2A,401-2A,32C,21F,201A,605A,401-1A,200-2E,583-58D,583/58E,583-57D,542,2B,1,542/2E,605B,32D,3,603,4,6,5,60,201C,542/2D,40,20,50,200-2C,21C,800A,200A,571-573B,51/2,470/1,51/1,571-573C,454-1,444-446";
List < String > items = Arrays.asList(input.split("\\s*,\\s*"));
System.out.println("items: " + items);
Pattern pattern = Pattern.compile("^\\d+");
Collections.sort(items, new Comparator < String > () {
public int compare(String o1, String o2) {
int intDiff = extractInt(o1) - extractInt(o2);
if (intDiff == 0) {
return o1.compareTo(o2);
}
return intDiff;
}
int extractInt(String s) {
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
String num = matcher.group(0);
return Integer.parseInt(num);
}
return 0;
}
});
for (String s: items) {
System.out.println(s);
}
}
}
This answer handles comparison between numbers like 20-10A and 20-2A
public static void main(String[] args) {
String s = "605,2A,401-2A,32C,21F,201A,605A,401-1A,200-2E,583-58D,583/58E,583-57D,542,2B,1,542/2E," +
"605B,32D,3,603,4,6,5,60,201C,542/2D,40,20,50,200-2C,21C,800A,200A,571-573B,51/2,470/1,51/1," +
"571-573C,454-1,444-446";
String[] strings = s.split(",");
Arrays.sort(strings, App::compare);
System.out.println(Arrays.deepToString(strings));
}
public static int compare(String o1, String o2) {
if (startsWithDelim(o1)) return compare(o1.substring(1), o2);
if (startsWithDelim(o2)) return compare(o1, o2.substring(1));
List<String> n1 = extractInt(o1);
List<String> n2 = extractInt(o2);
if (n1 != null && n2 != null) {
Integer n1int = Integer.parseInt(n1.get(0));
Integer n2int = Integer.parseInt(n2.get(0));
String n1Remaining = n1.get(1);
String n2Remaining = n2.get(1);
int intCompare = n1int.compareTo(n2int);
return intCompare == 0 ? compare(n1Remaining, n2Remaining) : intCompare;
}
if (n1 == null && n2 == null)
return o1.compareTo(o2);
else if (n1 == null) return -1;
else return 1;
}
static List<String> extractInt(String s) {
Pattern pattern = Pattern.compile("^\\d+");
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
String num = matcher.group(0);
return List.of(num, s.substring(matcher.end(0)));
}
return null;
}
static boolean startsWithDelim(String s) {
return (s.startsWith("/") || s.startsWith("-"));
}
I will provide some tips
In order compare the items 1,20,200-2C,3,32C,32D,4 (this is the default sort order, as string) you need to check if any number is included in the string. This can be done using a regular expression. You can find a lot of examples online with regular expressions that can bring you the numbers in the string back.
Modify your comparator and check if any of the two string that are to be compared include any number and return the appropriate result.
the extractInt method can be similar to as #Pankaj Saini 's suggestion
Integer extractInt(String s) {
Pattern pattern = Pattern.compile("^\\d+");
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
String num = matcher.group(0);
return Integer.parseInt(num);
}
return null;
}
The compare method can be like this
public int compare(String o1, String o2) {
if(extractInt(o1)!=null && extractInt(o2)!=null){
if(extractInt(o1).equals(extractInt(o2)))
{
return o1.substring(extractInt(o1).toString().length())
.compareTo(o2.substring(extractInt(o2).toString().length()));
}
return extractInt(o1).compareTo(extractInt(o2));
}
else if(extractInt(o1)!=null)
{
return -1;
}
else if(extractInt(o2)!=null)
{
return 1;
}
else{
return o1.compareTo(o2);
}
}
The purpose of this code is is to define the root of the sum of the squares.
I cant figure out how to put i into j. Please help.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int input, som, i=0;
int j = 0;
double answer;
Boolean gaDoor= true;
int [] array = new int [24];
while (gaDoor)
{
Console.Write("Specify a positive integer");
input = Convert.ToInt32(Console.ReadLine());
if (input == -1)
{
gaDoor = false;
}
else
{
if (input >= 0)
{
array[i] = input;
i++;
}
else
{
Console.WriteLine("Specify a positive integer ");
}
}
}
while (j<i)
{
sum = array [j] ^ 2;
answer = Math.Sqrt(sum);
Console.Write(answer);
}
Console.ReadKey();
}
}
}
using System;
namespace Test
{
class MainClass
{
public static void Main (string[] args)
{
int[] invoer = new int[24];
double[] resultaat = new double[24];
double totaal = 0;
double wortel = 0;
int commando = 0;
int teller = -1;
try {
// Keep going until a negative integer is entered (or a 0)
while ((commando = Convert.ToInt32 (Console.ReadLine ())) > 0) {
teller++;
invoer [teller] = commando;
}
} catch (FormatException) {
// Not a number at all.
}
teller = -1;
foreach (int i in invoer) {
teller++;
resultaat [teller] = Math.Pow (invoer [teller], 2);
totaal += resultaat [teller];
if (invoer [teller] > 0) {
Console.WriteLine ("Invoer: {0}, Resultaat: {1}", invoer [teller], resultaat [teller]);
}
}
wortel = Math.Sqrt (totaal);
Console.WriteLine ("Totaal: {0}, Wortel: {1}", totaal, wortel);
}
}
}