Sort 2 Numbers in ArrayList Using C#? - sorting

I am using an ArrayList to store objects of the class called SocialTimes. SocialTimes holds a string and 2 numbers. I'm trying to sort based on the Hour and Minute. I have no clue of how to do it. Can someone help me?
public class SocialTimes
{
string DateToPostStr = "";
int HourToPost = 0;
int MinuteToPost = 0;
public SocialTimes(string DateToPostStr, int HourToPost, int MinuteToPost)
{
this.DateToPostStr = DateToPostStr;
this.HourToPost = HourToPost;
this.MinuteToPost = MinuteToPost;
}
public string getDateToPostStr()
{
return this.DateToPostStr;
}
public int getHourToPost()
{
return this.HourToPost;
}
public int getMinuteToPost()
{
return this.MinuteToPost;
}
public static implicit operator SocialTimes(ArrayList v)
{
throw new NotImplementedException();
}
}
public class myComparer : IComparer
{
int IComparer.Compare(Object xx, Object yy)
{
SocialTimes x = (SocialTimes)xx;
SocialTimes y = (SocialTimes)yy;
return x.getHourToPost().CompareTo(y.getHourToPost());
}
}
So here is a method to test the sort ArrayList...
private void testHourMinuteSort()
{
ArrayList projects = new ArrayList();
projects.Add(new SocialTimes("03/14/20", 17, 7));
projects.Add(new SocialTimes("03/14/20", 10, 39));
projects.Add(new SocialTimes("03/14/20", 12, 7));
projects.Add(new SocialTimes("03/14/20", 3, 16));
projects.Add(new SocialTimes("03/14/20", 21, 8));
projects.Add(new SocialTimes("03/14/20", 20, 56));
projects.Add(new SocialTimes("03/14/20", 3, 2));
projects.Sort(new myComparer());
string hoursminutes = "";
foreach (SocialTimes item in projects)
{
hoursminutes = hoursminutes + String.Format("Hour: {0} Minute: {1}", item.getHourToPost(), item.getMinuteToPost()) + Environment.NewLine;
}
MessageBox.Show(hoursminutes);
}
hoursminutes:
Hour: 3 Minute: 16
Hour: 3 Minute: 2
Hour: 10 Minute: 39
Hour: 12 Minute: 7
Hour: 17 Minute: 7
Hour: 20 Minute: 56
Hour: 21 Minute: 8
I need the sort to sort by hours and minutes like below.
Hour: 3 Minute: 2
Hour: 3 Minute: 16
Hour: 10 Minute: 39
Hour: 12 Minute: 7
Hour: 17 Minute: 7
Hour: 20 Minute: 56
Hour: 21 Minute: 8

Convert the values to minutes and compare, not just hours.
int x1 = t1.Hours * 60 + t1.Minutes;
As it is now, times with the same number of (whole) hours will be sorted “randomly” with respect to each other because the minutes are not compared.
Alternatively, just use LINQ and something like:
s.OrderBy(x => x.Hours).ThenBy(x => x.Minutes)
It would probably also be more clear to use a a Date and/or TimeSpan which represents dates and/or ranges of time well. In that case the above code would be simplified as only one value would be compared.
Using a proper generic collection type such as List<SocialTimes> is also a much more modern and type-safe way to deal with collections.

Related

Error handling for SimpleDateFormat in Java

I am writing a program that takes a users input for hours and minutes in the format HH:MM, and returns a string of that input. For example, 13:56 would be "four minutes to two".
I have created the code to do exactly that - take the input in that format and return a value as above. My issue is that I am not sure how to handle errors. I have a while loop that is meant to catch errors but it doesn't. I mainly want to ensure that if the user enters a character input (ee:rb or 12:bb etc.) or an invalid time (14:68 (I am going on a 12 hour clock)), that the program says "Error!" and makes the user try again.
I have worked with exception handling, but have not done so for SimpleDateFormat and I can't figure out why the below does not work.
Try this:
public static void main(String[] args) {
boolean safetyNet = false;
Scanner in = new Scanner(System.in);
Date d = new Date();
SimpleDateFormat simpFormat = new SimpleDateFormat("hh:mm");
while (!safetyNet) {
System.out.println("Please enter the time in hours and minutes: ");
String timeToString = in.next();
try {
d = simpFormat.parse(timeToString);
safetyNet = true;
String sHours = timeToString.substring(0, 2);
String sMinutes = timeToString.substring(3);
int hours = Integer.parseInt(sHours);
int minutes = Integer.parseInt(sMinutes);
String time=getTimeName(hours, minutes);
if(time.isEmpty()){
safetyNet = false;
}else{
System.out.printf("Time is: " + getTimeName(hours, minutes));
}
} catch (ParseException e) {
System.out.println("Error! Try again: ");
// e.printStackTrace();
}
}
in.close();
}
public static String getTimeName(int hours, int minutes) {
String timeName = "";
if (hours >= 1 && hours <= 12 && minutes >= 0 && minutes <= 59) {
String hourBank[] = { "", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten",
"Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen",
"Nineteen", "Twenty", "Twenty one", "Twenty two", "Twenty three", "Twenty four", "Twenty five",
"Twenty six", "Twenty seven", "Twenty eight", "Twenty nine" };
if (minutes == 0) {
timeName = hourBank[hours] + " O'clock";
}
else if (minutes == 15) {
timeName = "A quarter past " + hourBank[hours];
}
else if (minutes == 30) {
timeName = "Half Past " + hourBank[hours];
}
else if (hours == 12 && minutes == 45) {
timeName = "A quarter to " + hourBank[hours - 11];
}
else if (minutes == 45) {
timeName = "A quarter to " + hourBank[hours + 1];
}
else if (minutes <= 29) {
timeName = hourBank[minutes] + " minutes past " + hourBank[hours];
}
else if (hours == 12 && minutes >= 31 && minutes <= 59) {
timeName = hourBank[60 - minutes] + " minutes to " + hourBank[hours - 11];
}
else if (minutes >= 31 && minutes <= 60) {
timeName = hourBank[60 - minutes] + " minutes to " + hourBank[hours + 1];
} else {
timeName = "That's not the correct format!";
}
}else{
System.out.println("minutes are between 0 and 60 and hours are between 0 and 12");
}
return timeName;
}
Given that you are just expecting a simple string hh:mm, I might use String#matches here:
do {
timeToString = in.nextLine();
} while (!timeToString.matches("(1[0-2]|0[1-9]):[0-5]\\d"));
This above loop will iterate until the users enters a valid 12 hour hour:minute string. If you don't like this approach, another approach would be to use SimpleDateFormat#parse to attempt to parse the input. This method throws a ParseException, so you could try catching and looping on that.

How to display all number by increment?

i was task to ask a user to enter a number in range from 1 to 15 and after 5 input, i suppose to display all the number that enter by the user.
saying the user enter 2, 3, 4, 5, and 6, this is what i suppose to display:
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
package barChartPrinting;
import java.util.Scanner;
public class barChart {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int getNumber;
for (int counter = 0; counter < 5; counter++){
System.out.println("Enter a numbers in range of 1 to 15: ");
getNumber = keyboard.nextInt();
while (getNumber < 1 || getNumber > 15){
System.out.println("Invalid number!, please re-enter: ");
getNumber = keyboard.nextInt();
}
}
//end of statement here
}
}

Determine day based on number

I just want to ask if how do you determine
Enter a number: 14
Then the date to day is Sunday.
the above demonstration is from 1-7=monday-sunday then if the value is 8 then its monday again...but how could I determine it?using loops and modulo?...
I appreciate any comments for helping me...
any language are ok, I just want to know the algorithm with it...
You can just use module
Module got to 0 so it would be something like
<?php
$value = 13;
$daynames = array("mon", "tues", "wed", "thur", "fri", "sat", "sun");
// The + 1 is because % is 0, and you want 1-7
echo (($value % 7) + 1) . "day of the week";
echo "the day is " . $daynames[($value % 7)];
?>
Example: http://codepad.org/wbGuMI06
If you have a switch/case or if/else for the seven days you can use modulo 7 to get the input into the desired range of 7 days.
You can use a switch statement and modulo arithmetic to do this.
The first step to learning computer science is to learn that numbers don't usually start at 1. They start at 0. Getting this idea down will help you tremendously in the future!
// accept numbers 0-6. If 7 were to get put in, it would end up being 0 since 7 % 7 = 0.
switch(num % 7) {
case 0: return "Sunday";
case 1: return "Monday";
case 2: return "Tuesday";
/// rest here...
default: throw new IllegalArgumentException();
}
Taking the number modulo 7 would seem like the obvious possibility.
In C++, int day = (i-1) % 7; will give you a zero-based offset. Here's sample code:
#include <iostream>
#include<string>
using namespace std;
int main()
{
static const std::string days [] =
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
static const size_t num_days = sizeof(days)/sizeof(days[0]);
for( int i = 1; i <= 31; ++i )
{
int day = (i-1) % 7;
cout << day << " = " << days[day] << "\n";
}
}
Get modulo 7 of the int value thats passed in and make a switch statement for it.
switch:
case 1:
Sunday
case 2:
Monday
// and so on
string day;
int inputNumber;
if(inputNumber%7 == 0)
day = "monday"; // or sunday if you prefer :p
else if(inputNumber%7 == 1)
day = tuesday
...
...
...
datArr= new Array ('Sun', 'Mon', 'Tue',Wen', 'Thu, 'Fri', 'Sat');
day =datArr[(daynum%7)];
If Sunday gets treated as day zero there is no need to subtract 1 after the modulo. Of course most of the solutions will fail with zero dive if an actual value of zero is encountered.
import java.util.Scanner;
public class TestMain {
private static final String[] DAYS = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thusday", "Friday", "Saturday" };
public static void main(final String[] args) {
System.out.print("Enter a number: ");
final Scanner scanner = new Scanner(System.in);
final int n = scanner.nextInt();
System.out.print("Then the date to day is " + DAYS[n % 7]);
}
}

Iterating over discrete periods of time within another period of time

I have a following table of periods which describes how often to ..say.. feed my fish:
--------------------------------------------------------
Period: Jan Feb March April May Jun Jul ... n - 1 .... n
--------------------------------------------------------
Val_1: 5 2 3 6 3 2 4 x x
Val_2 ...
--------------------------------------------------------
And I have a period given with two DateTimes, start and end, ie:
DateTime start = new DateTime(2010, 3, 11);
DateTime end = new DateTime(2012, 7, 12);
..in which time the feeding process occurs. How can I get the values from the table in every period in correlation with the period given by start and end ?
For example, the period given by start and end is 2.5 years, but my table only describes 12 months. How can I loop over every period in the table WITHIN the whole period given by start and end ?
I came up with something like this:
class PeriodTableValue
{
DateTime period; // Ignore year component of datetime
double val_1;
double val_2;
}
void FeedMyFish(double howmuch, DateTime period_start, DateTime period_end)
{
...
}
...
PeriodTableValue[] table = ...
DateTime start = ...
DateTime end = ...
DateTime d1 = start;
for(int i = 0; i < table.Length; i++)
{
DateTime d2 = table[i].period;
int nI = find the occurrances of period table[i]. How ???
for(int j = 0; j < nI; j++)
{
FeedMyFish(..parameters ???)
}
d1 = d2;
}
And I'm stuck right here. Please advise.
Thanks!
This article includes support for various period types and the search for intersection periods:
// ----------------------------------------------------------------------
public void TimePeriodIntersectorSample()
{
TimePeriodCollection periods = new TimePeriodCollection();
periods.Add( new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 05 ), new DateTime( 2011, 3, 15 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 12 ), new DateTime( 2011, 3, 18 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 24 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 22 ), new DateTime( 2011, 3, 28 ) ) );
periods.Add( new TimeRange( new DateTime( 2011, 3, 24 ), new DateTime( 2011, 3, 26 ) ) );
TimePeriodIntersector<TimeRange> periodIntersector =
new TimePeriodIntersector<TimeRange>();
ITimePeriodCollection intersectedPeriods = periodIntersector.IntersectPeriods( periods );
foreach ( ITimePeriod intersectedPeriod in intersectedPeriods )
{
Console.WriteLine( "Intersected Period: " + intersectedPeriod );
}
// > Intersected Period: 05.03.2011 - 10.03.2011 | 5.00:00
// > Intersected Period: 12.03.2011 - 15.03.2011 | 3.00:00
// > Intersected Period: 22.03.2011 - 26.03.2011 | 4.00:00
} // TimePeriodIntersectorSample

algorithm to sum up a list of numbers for all combinations

I have a list of numbers and I want to add up all the different combinations.
For example:
number as 1,4,7 and 13
the output would be:
1+4=5
1+7=8
1+13=14
4+7=11
4+13=17
7+13=20
1+4+7=12
1+4+13=18
1+7+13=21
4+7+13=24
1+4+7+13=25
Is there a formula to calculate this with different numbers?
A simple way to do this is to create a bit set with as much bits as there are numbers.
In your example 4.
Then count from 0001 to 1111 and sum each number that has a 1 on the set:
Numbers 1,4,7,13:
0001 = 13=13
0010 = 7=7
0011 = 7+13 = 20
1111 = 1+4+7+13 = 25
Here's how a simple recursive solution would look like, in Java:
public static void main(String[] args)
{
f(new int[] {1,4,7,13}, 0, 0, "{");
}
static void f(int[] numbers, int index, int sum, String output)
{
if (index == numbers.length)
{
System.out.println(output + " } = " + sum);
return;
}
// include numbers[index]
f(numbers, index + 1, sum + numbers[index], output + " " + numbers[index]);
// exclude numbers[index]
f(numbers, index + 1, sum, output);
}
Output:
{ 1 4 7 13 } = 25
{ 1 4 7 } = 12
{ 1 4 13 } = 18
{ 1 4 } = 5
{ 1 7 13 } = 21
{ 1 7 } = 8
{ 1 13 } = 14
{ 1 } = 1
{ 4 7 13 } = 24
{ 4 7 } = 11
{ 4 13 } = 17
{ 4 } = 4
{ 7 13 } = 20
{ 7 } = 7
{ 13 } = 13
{ } = 0
The best-known algorithm requires exponential time. If there were a polynomial-time algorithm, then you would solve the subset sum problem, and thus the P=NP problem.
The algorithm here is to create bitvector of length that is equal to the cardinality of your set of numbers. Fix an enumeration (n_i) of your set of numbers. Then, enumerate over all possible values of the bitvector. For each enumeration (e_i) of the bitvector, compute the sum of e_i * n_i.
The intuition here is that you are representing the subsets of your set of numbers by a bitvector and generating all possible subsets of the set of numbers. When bit e_i is equal to one, n_i is in the subset, otherwise it is not.
The fourth volume of Knuth's TAOCP provides algorithms for generating all possible values of the bitvector.
C#:
I was trying to find something more elegant - but this should do the trick for now...
//Set up our array of integers
int[] items = { 1, 3, 5, 7 };
//Figure out how many bitmasks we need...
//4 bits have a maximum value of 15, so we need 15 masks.
//Calculated as:
// (2 ^ ItemCount) - 1
int len = items.Length;
int calcs = (int)Math.Pow(2, len) - 1;
//Create our array of bitmasks... each item in the array
//represents a unique combination from our items array
string[] masks = Enumerable.Range(1, calcs).Select(i => Convert.ToString(i, 2).PadLeft(len, '0')).ToArray();
//Spit out the corresponding calculation for each bitmask
foreach (string m in masks)
{
//Get the items from our array that correspond to
//the on bits in our mask
int[] incl = items.Where((c, i) => m[i] == '1').ToArray();
//Write out our mask, calculation and resulting sum
Console.WriteLine(
"[{0}] {1}={2}",
m,
String.Join("+", incl.Select(c => c.ToString()).ToArray()),
incl.Sum()
);
}
Outputs as:
[0001] 7=7
[0010] 5=5
[0011] 5+7=12
[0100] 3=3
[0101] 3+7=10
[0110] 3+5=8
[0111] 3+5+7=15
[1000] 1=1
[1001] 1+7=8
[1010] 1+5=6
[1011] 1+5+7=13
[1100] 1+3=4
[1101] 1+3+7=11
[1110] 1+3+5=9
[1111] 1+3+5+7=16
Here is a simple recursive Ruby implementation:
a = [1, 4, 7, 13]
def add(current, ary, idx, sum)
(idx...ary.length).each do |i|
add(current + [ary[i]], ary, i+1, sum + ary[i])
end
puts "#{current.join('+')} = #{sum}" if current.size > 1
end
add([], a, 0, 0)
Which prints
1+4+7+13 = 25
1+4+7 = 12
1+4+13 = 18
1+4 = 5
1+7+13 = 21
1+7 = 8
1+13 = 14
4+7+13 = 24
4+7 = 11
4+13 = 17
7+13 = 20
If you do not need to print the array at each step, the code can be made even simpler and much faster because no additional arrays are created:
def add(ary, idx, sum)
(idx...ary.length).each do |i|
add(ary, i+1, sum + ary[i])
end
puts sum
end
add(a, 0, 0)
I dont think you can have it much simpler than that.
Mathematica solution:
{#, Total##}& /# Subsets[{1, 4, 7, 13}] //MatrixForm
Output:
{} 0
{1} 1
{4} 4
{7} 7
{13} 13
{1,4} 5
{1,7} 8
{1,13} 14
{4,7} 11
{4,13} 17
{7,13} 20
{1,4,7} 12
{1,4,13} 18
{1,7,13} 21
{4,7,13} 24
{1,4,7,13} 25
This Perl program seems to do what you want. It goes through the different ways to choose n items from k items. It's easy to calculate how many combinations there are, but getting the sums of each combination means you have to add them eventually. I had a similar question on Perlmonks when I was asking How can I calculate the right combination of postage stamps?.
The Math::Combinatorics module can also handle many other cases. Even if you don't want to use it, the documentation has a lot of pointers to other information about the problem. Other people might be able to suggest the appropriate library for the language you'd like to you.
#!/usr/bin/perl
use List::Util qw(sum);
use Math::Combinatorics;
my #n = qw(1 4 7 13);
foreach my $count ( 2 .. #n ) {
my $c = Math::Combinatorics->new(
count => $count, # number to choose
data => [#n],
);
print "combinations of $count from: [" . join(" ",#n) . "]\n";
while( my #combo = $c->next_combination ){
print join( ' ', #combo ), " = ", sum( #combo ) , "\n";
}
}
You can enumerate all subsets using a bitvector.
In a for loop, go from 0 to 2 to the Nth power minus 1 (or start with 1 if you don't care about the empty set).
On each iteration, determine which bits are set. The Nth bit represents the Nth element of the set. For each set bit, dereference the appropriate element of the set and add to an accumulated value.
ETA: Because the nature of this problem involves exponential complexity, there's a practical limit to size of the set you can enumerate on. If it turns out you don't need all subsets, you can look up "n choose k" for ways of enumerating subsets of k elements.
PHP: Here's a non-recursive implementation. I'm not saying this is the most efficient way to do it (this is indeed exponential 2^N - see JasonTrue's response and comments), but it works for a small set of elements. I just wanted to write something quick to obtain results. I based the algorithm off Toon's answer.
$set = array(3, 5, 8, 13, 19);
$additions = array();
for($i = 0; $i < pow(2, count($set)); $i++){
$sum = 0;
$addends = array();
for($j = count($set)-1; $j >= 0; $j--) {
if(pow(2, $j) & $i) {
$sum += $set[$j];
$addends[] = $set[$j];
}
}
$additions[] = array($sum, $addends);
}
sort($additions);
foreach($additions as $addition){
printf("%d\t%s\n", $addition[0], implode('+', $addition[1]));
}
Which will output:
0
3 3
5 5
8 8
8 5+3
11 8+3
13 13
13 8+5
16 13+3
16 8+5+3
18 13+5
19 19
21 13+8
21 13+5+3
22 19+3
24 19+5
24 13+8+3
26 13+8+5
27 19+8
27 19+5+3
29 13+8+5+3
30 19+8+3
32 19+13
32 19+8+5
35 19+13+3
35 19+8+5+3
37 19+13+5
40 19+13+8
40 19+13+5+3
43 19+13+8+3
45 19+13+8+5
48 19+13+8+5+3
For example, a case for this could be a set of resistance bands for working out. Say you get 5 bands each having different resistances represented in pounds and you can combine bands to sum up the total resistance. The bands resistances are 3, 5, 8, 13 and 19 pounds. This set gives you 32 (2^5) possible configurations, minus the zero. In this example, the algorithm returns the data sorted by ascending total resistance favoring efficient band configurations first, and for each configuration the bands are sorted by descending resistance.
This is not the code to generate the sums, but it generates the permutations. In your case:
1; 1,4; 1,7; 4,7; 1,4,7; ...
If I have a moment over the weekend, and if it's interesting, I can modify this to come up with the sums.
It's just a fun chunk of LINQ code from Igor Ostrovsky's blog titled "7 tricks to simplify your programs with LINQ" (http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/).
T[] arr = …;
var subsets = from m in Enumerable.Range(0, 1 << arr.Length)
select
from i in Enumerable.Range(0, arr.Length)
where (m & (1 << i)) != 0
select arr[i];
You might be interested in checking out the GNU Scientific Library if you want to avoid maintenance costs. The actual process of summing longer sequences will become very expensive (more-so than generating a single permutation on a step basis), most architectures have SIMD/vector instructions that can provide rather impressive speed-up (I would provide examples of such implementations but I cannot post URLs yet).
Thanks Zach,
I am creating a Bank Reconciliation solution. I dropped your code into jsbin.com to do some quick testing and produced this in Javascript:
function f(numbers,ids, index, sum, output, outputid, find )
{
if (index == numbers.length){
var x ="";
if (find == sum) {
y= output + " } = " + sum + " " + outputid + " }<br/>" ;
}
return;
}
f(numbers,ids, index + 1, sum + numbers[index], output + " " + numbers[index], outputid + " " + ids[index], find);
f(numbers,ids, index + 1, sum, output, outputid,find);
}
var y;
f( [1.2,4,7,13,45,325,23,245,78,432,1,2,6],[1,2,3,4,5,6,7,8,9,10,11,12,13], 0, 0, '{','{', 24.2);
if (document.getElementById('hello')) {
document.getElementById('hello').innerHTML = y;
}
I need it to produce a list of ID's to exclude from the next matching number.
I will post back my final solution using vb.net
v=[1,2,3,4]#variables to sum
i=0
clis=[]#check list for solution excluding the variables itself
def iterate(lis,a,b):
global i
global clis
while len(b)!=0 and i<len(lis):
a=lis[i]
b=lis[i+1:]
if len(b)>1:
t=a+sum(b)
clis.append(t)
for j in b:
clis.append(a+j)
i+=1
iterate(lis,a,b)
iterate(v,0,v)
its written in python. the idea is to break the list in a single integer and a list for eg. [1,2,3,4] into 1,[2,3,4]. we append the total sum now by adding the integer and sum of remaining list.also we take each individual sum i.e 1,2;1,3;1,4. checklist shall now be [1+2+3+4,1+2,1+3,1+4] then we call the new list recursively i.e now int=2,list=[3,4]. checklist will now append [2+3+4,2+3,2+4] accordingly we append the checklist till list is empty.
set is the set of sums and list is the list of the original numbers.
Its Java.
public void subSums() {
Set<Long> resultSet = new HashSet<Long>();
for(long l: list) {
for(long s: set) {
resultSet.add(s);
resultSet.add(l + s);
}
resultSet.add(l);
set.addAll(resultSet);
resultSet.clear();
}
}
public static void main(String[] args) {
// this is an example number
long number = 245L;
int sum = 0;
if (number > 0) {
do {
int last = (int) (number % 10);
sum = (sum + last) % 9;
} while ((number /= 10) > 0);
System.err.println("s = " + (sum==0 ? 9:sum);
} else {
System.err.println("0");
}
}

Resources