I'm fairly new to coding and am struggling with an assignment for my class. The program takes a user input for the size of an Array and prompts the user to enter each value 1 at a time. The array size starts at 3 and if the array needs to be bigger when the array has filled a new array that's 2x size is created and all info is copied into it. I was able to figure out this part but I just can't see what I'm doing wrong in the downsizing part. After the info is copied I have to remove the trailing zeroes. I think I have the downsize method right but I don't know if I'm calling it right
import java.util.Scanner;
public class Lab6 {
public static void main(String args[]) {
int[] myarray = new int[3];
int count = 0;
int limit, limitcount = 1;
Scanner kbd = new Scanner(System.in);
System.out.print("How many values would you like to enter? ");
limit = kbd.nextInt();
while (limitcount <= limit) {
System.out.println("Enter an integer value ");
int input = kbd.nextInt();
limitcount++;
if (count < myarray.length) {
myarray[count] = input;
}
else {
myarray = upsize(myarray);
myarray[count] = input;
}
count++;
}
myarray = downsize(myarray, count)
printArray(myarray);
System.out.println("The amount of values in the arrays that we care about is: " + count);
}
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
for (int i =0;i<array.length; i++) {
bigger[i] = array[i];
}
return bigger;
}
static void printArray( int[] array ) {
for ( int number : array ) {
System.out.print( number + " ");
}
System.out.println();
}
static int[] downsize(int[] array,int count) {
int[] smaller = new int[count];
for (int i =0; i<count; i++) {
smaller[i] = array[i];
}
return array;
}
}
Giving you a full response rather than a comment since you're new here and I don't want to discourage you with brevity which could be misunderstood.
Not sure what happened to your code when you pasted it in here, you've provided everything but the format is weird (the 'code' bit is missing out a few lines at the top and bottom). Might be one to double-check before posting. After posting, I see that someone else has already edited your code to fix this one.
You're missing a semi-colon. I'm not a fan of handing out answers, so I'll leave you to find it :) If you're running your code in an IDE, it should already be flagging that one up for you. If you're not, why on earth not??? IntelliJ is free, easy to get going with, and incredibly helpful. There are others out there as well which different folk prefer :) An IDE will help you spot all sorts of useful things quickly.
I have now run your code, and you do have a problem! It's in your final method, downsize(). Look very, very carefully at the return statement ;) Your questions suggests you aren't actually sure whether or not this method is right, which makes me wonder: have you actually run this code with different inputs to see what results you get? Please do that.
Style-wise: blank lines between methods would make the code easier to look at, by providing a visual gap between components. Please be consistent with putting your opening { on the same line as the method signature, and with having spaces between items, e.g. for (int i = 0; i < count; i++) rather than for (int i =0; i<count; i++). The compiler couldn't care less, but it is easier for humans to look at and just makes it look like you did care. Always a good thing!
I think it is awesome that you are separating some of the work into smaller methods. Seriously. For extra brownie points, think about how you could move that while() block into its own method, e.g. private int[] getUserData(int numberOfItems, Scanner scanner). Your code is great without this, but the more you learn to write tiny units, the more favours you will be doing your future self.
Has your class looked at unit testing yet? Trust me, if not, when you get to this you will realise just how important point 5 can be. Unit tests will also help a lot with issues such as the one in point 3 above.
Overall, it looks pretty good to me. Keep going!!!
Simple mistake in your downsize method. If you have an IDE like Eclipse, Intellij, etc. you would have seen it flagged right away.
return array; // should return smaller
I have a few suggestions since you mentioned being new to coding.
The "limitcount" variable can be removed and substituted with "count" at every instance. I'll leave it to you to figure that out.
Try using more descriptive and understandable variable names. Other people will read your code (like now) and appreciate it.
Try to use consistent spacing/indentation throughout your code.
Your upsize method can be simplified using a System.arraycopy() call which generally performs better and avoids the need for writing out a for loop. You can rewrite downsize in a similar manner.
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
System.arraycopy(array, 0, bigger, 0, array.length);
return bigger;
}
Edit: All good points by sunrise above - especially that you've done well given your experience. You should set up an IDE when you have the time, they're simple to use and invaluable. When you do so you should learn to step through a debugger to explore the state of your program over time. In this case you would have noticed that the myarray variable was never reassigned after the downsize() call, quickly leading you to a solution (if you had missed the warning about an unused "smaller" array).
I'm working on a programming practice site that asked to implement a method that merges two sorted arrays. This is my solution:
public static int[] merge(int[] arrLeft, int[] arrRight){
int[] merged = new int[arrRight.length + arrLeft.length];
Queue<Integer> leftQueue = new LinkedList<>();
Queue<Integer> rightQueue = new LinkedList<>();
for(int i = 0; i < arrLeft.length ; i ++){
leftQueue.add(arrLeft[i]);
}
for(int i = 0; i < arrRight.length; i ++){
rightQueue.add(arrRight[i]);
}
int index = 0;
while (!leftQueue.isEmpty() || !rightQueue.isEmpty()){
int largerLeft = leftQueue.isEmpty() ? Integer.MAX_VALUE : leftQueue.peek();
int largerRight = rightQueue.isEmpty() ? Integer.MAX_VALUE : rightQueue.peek();
if(largerLeft > largerRight){
merged[index] = largerRight;
rightQueue.poll();
} else{
merged[index] = largerLeft;
leftQueue.poll();
}
index ++;
}
return merged;
}
But this is the official solution:
public static int[] merge(int[] arrLeft, int[] arrRight){
// Grab the lengths of the left and right arrays
int lenLeft = arrLeft.length;
int lenRight = arrRight.length;
// Create a new output array with the size = sum of the lengths of left and right
// arrays
int[] arrMerged = new int[lenLeft+lenRight];
// Maintain 3 indices, one for the left array, one for the right and one for
// the merged array
int indLeft = 0, indRight = 0, indMerged = 0;
// While neither array is empty, run a while loop to merge
// the smaller of the two elements, starting at the leftmost position of
// both arrays
while(indLeft < lenLeft && indRight < lenRight){
if(arrLeft[indLeft] < arrRight[indRight])
arrMerged[indMerged++] = arrLeft[indLeft++];
else
arrMerged[indMerged++] = arrRight[indRight++];
}
// Another while loop for when the left array still has elements left
while(indLeft < lenLeft){
arrMerged[indMerged++] = arrLeft[indLeft++];
}
// Another while loop for when the right array still has elements left
while(indRight < lenRight){
arrMerged[indMerged++] = arrRight[indRight++];
}
return arrMerged;
}
Apparently, all the other solutions by users on the site did not make use of a queue as well. I'm wondering if using a Queue is less efficient? Could I be penalized for using a queue in an interview for example?
As the question already states that the left and right input arrays are sorted, this gives you a hint that you should be able to solve the problem without requiring a data structure other than an array for the output.
In a real interview, it is likely that the interviewer will ask you to talk through your thought process while you are coding the solution. They may state that they want the solution implemented with certain constraints. It is very important to make sure that the problem is well defined before you start your coding. Ask as many questions as you can think of to constrain the problem as much as possible before starting.
When you are done implementing your solution, you could mention the time and space complexity of your implementation and suggest an alternative, more efficient solution.
For example, when describing your implementation you could talk about the following:
There is overhead when creating the queues
The big O notation / time and space complexity of your solution
You are unnecessarily iterating over every element of the left and right input array to create the queues before you do any merging
etc...
These types of interview questions are common when applying for positions at companies like Google, Microsoft, Amazon, and some tech startups. To prepare for such questions, I recommend you work through problems in books such as Cracking the Coding Interview. The book covers how to approach such problems, and the interview process for these kinds of companies.
Sorry to say but your solution with queues is horrible.
You are copying all elements to auxiliary dynamic data structures (which can be highly costly because of memory allocations), then back to the destination array.
A big "disadvantage" of merging is that it requires twice the storage space as it cannot be done in-place (or at least no the straightforward way). But you are spoiling things to a much larger extent by adding extra copies and overhead, unnecessarily.
The true solution is to copy directly from source to destination, leading to simpler and much more efficient code.
Also note that using a sentinel value (Integer.MAX_VALUE) when one of the queues is exhausted is a false good idea because it adds extra comparisons when you know the outcome in advance. It is much better to split in three loops as in the reference code.
Lastly, your solution can fail when the data happens to contain Integer.MAX_VALUE.
I want to make a program that each semester, creates a schedule depending of a list of classes I input, so if I add various classes, depending of the time and days that these classes will happen then the program would be able to match what classes can be added without intercepting each other. I want to know if there is an algorithms or way of comparing the class schedule in order to determine what classes can I have from the list of courses.
The only way of doing these that I can imagine is with many if statements or adding an starting course and then having an array that tracks the hours, starting each position at 0 and then each time an hour is occupied I change the array position to 1. Then when adding a course I check what positions are different to 1 and try to add the class.
I want to find a more optimal solution to this problem than the ones I can imagine.
This is a planning problem. Planning problem are very difficult to solve in a efficient way: performance issues arise very quickly in this kind of problem.
If you just want to solve the problem, you should check an existing planning problem solver like OptaPlanner: it's open source, so you can try to understand how it work and there is a blog with interresting thoughts about planning problem.
If you're wanting a method where, given a group of classes with their times and a chosen class, output the available classes, you can use simple iteration to do the job. Suppose you have a 5 hour slot with 4 classes you could represent each class with a single array:
int[][] times = {
{0,1,1,0,0},
{1,1,0,0,0},
{0,1,0,0,0},
{0,0,0,1,1}
};
So if you were to choose the class taking up the last 2hrs then the remaining options would be:
{0,1,1,0,0},
{1,1,0,0,0},
{0,1,0,0,0}
Given this representation you could do something like:
import java.util.*;
public class C {
static int[][] available(int[] c,int[][] times){
ArrayList<Integer> index = new ArrayList<>();
ArrayList<Integer> result = new ArrayList<>();
for(int i=0;i<c.length;i++)
if(c[i]==1) index.add(i);
for(int i = 0; i < times.length; i++){
if(!times[i].equals(c)) {
for (int j = 0; j < times[0].length; j++) {
if(times[i][j]==1){
if(index.contains(j)) break;
}
if(j==times[0].length-1) result.add(i);
}
}
}
int[][] r = new int[result.size()][c.length];
for(int i=0;i<result.size();i++){
r[i] = times[result.get(i)];
}
return r;
}
public static void main(String[] args) {
int[][] times = {
{0,1,1,0,0},
{1,1,0,0,0},
{0,1,0,0,0},
{0,0,0,1,1}
};
int[] c = {0,0,0,1,1};
available(c,times);
System.out.println(Arrays.deepToString(available(c,times)));
}
}
Here's the problem that I have:
I need to compare two ArrayLists and return if they are the same or if they are different, return the elements that are new from one of them, the pivot so to speak.
Here's the behaviour of the data-set:
the two ArrayLists are made of Strings
they're populated from the same source so are most of the time the same
are ordered (in the sense of the custom logic attached to them)
there will never be any empty Strings
all of the Strings have the same length, always
no duplicates
What I want:
the fastest possible way of achieving my two goals, whichever the case
using only Java 1.6 standard library features, I'd prefer not to implement a hybrid class that emulated something from List and then Set for example.
Example:
A: [ 'a', 'b', 'c', 'd']
B: [ 'a', 'c', 'd']
Result: Lists are different, return the element 'b'; A will be the 'work' List, we will make comparisons based on what's new in this ArrayList, since B will never change.
Thanks for any replies and your input.
Your fastest possible requirement bothers me a lot--I'm quite against optimizing--I generally consider early optimization one of the worst programming practices around.
If you really want to do that, just walk the two lists in order.
if the first entries match, you put that one into a "Same" pile and increment both indexes. If they are different, put the first (lower/less-than) one into a "Different" pile and increment that lists index. Loop this way until you hit the end of one list (any remaining in the other obviously go into the "Different" collection.
That should give you "close" to the fastest way. If you want the absolute fastest then you have to start by using arrays, not lists, and then pay a lot of attention to what else you do every step of the way--but the algorithm should still be pretty close to optimal.
As an example of sub-optimal but much more readable you could use some set manipulation.
Set set1=new HashSet(list1)
Set set2=new HashSet(list2)
Set same=set1.retainAll(set2) // I forget if retainAll modifies set1--if so you need to copy it first
set1.removeAll(list2)
set2.removeAll(list1)
Set different=set1.addAll(set2)
// at this point same contains all the similar values and different contains the ones that don't match. Done.
This is short and readable and probably more performant than you would think. It would be bad practice to code your own if something like this works well enough (Say, in GUI code where speed is unlikely to matter).
Pretty simple (assuming the list is ordered ascending, can be easily changed for descending order):
ArrayList<String> delta(ArrayList<String> a , ArrayList<String> b , Comparator<String> comp){
if(a.isEmpty())
return new ArrayList(b);
if(b.isEmpty())
return new ArrayList(a);
Iterator<String> it_a = a.iterator();
Iterator<String> it_b = b.iterator();
ArrayList<String> delta = new ArrayList<>();
String a_s = it_a.next() , b_s = it_b.next();
boolean onechecked = false;
while(!onechecked){
int comp_v = comp.compare(a_s , b_s);
if(comp_v == 0){
//strings are equal -> ommit them
if(it_a.hasNext())
a_s = it_a.next();
else
onechecked = true;
if(it_b.hasNext())
b_s = it_b.next();
else
onechecked = true;
}else if(comp_v < 0){
//a_s is not part of b
delta.add(a_s);
if(it_a.hasNext())
a_s = it_a.next();
else
onechecked = true;
}else{
//b_s is not part of a
delta.add(b_s);
if(it_b.hasNext())
b_s = it_b.next();
else
onechecked = true;
}
}
//add remaining items
delta.add(it_a.hasNext() ? a_s : b_s);
for(Iterator<String> it = (it_a.hasNext() ? it_a : it_b) ; it.hasNext();)
delta.add(it.next());
return delta;
}
Sorry for not adding any explanation, but the code has to speak for itself, since i have no idea how to explain it.
I have the following problem:
I have 2 Strings of DNA Sequences (consisting of ACGT), which differ in one or two
spots.
Finding the differences is trivial, so let's just ignore that
for each difference, I want to get the consensus symbol (e.g. M for A or C) that represents both possibilities
I know I could just make a huge if-cascade but I guess that's not only ugly and hard to maintain, but also slow.
What is a fast, easy to maintain way to implement that? Some kind of lookup table perhaps, or a matrix for the combinations? Any code samples would be greatly appreciated. I would have used Biojava, but the current version I am already using does not offer that functionality (or I haven't found it yet...).
Update: there seems to be a bit of confusion here. The consensus symbol is a single char, that stands for a single char in both sequences.
String1 and String2 are, for example "ACGT" and "ACCT" - they mismatch on position 2. Sooo, I want a consensus string to be ACST, because S stands for "either C or G"
I want to make a method like this:
char getConsensus(char a, char b)
Update 2: some of the proposed methods work if I only have 2 sequences. I might need to do several iterations of these "consensifications", so the input alphabet could increase from "ACGT" to "ACGTRYKMSWBDHVN" which would make some of the proposed approaches quite unwieldy to write and maintain.
You can just use a HashMap<String, String> which maps the conflicts/differences to the consensus symbols. You can either "hard code" (fill in the code of your app) or fill it during the startup of your app from some outside source (a file, database etc.). Then you just use it whenever you have a difference.
String consensusSymbol = consensusMap.get(differenceString);
EDIT: To accomodate your API request ;]
Map<String, Character> consensusMap; // let's assume this is filled somewhere
...
char getConsensus(char a, char b) {
return consensusMap.get("" + a + b);
}
I realize this look crude but I think you get the point. This might be slightly slower than a lookup table but it's also a lot easier to maintain.
YET ANOTHER EDIT:
If you really want something super fast and you actuall use the char type you can just create a 2d table and index it with characters (since they're interpreted as numbers).
char lookup[][] = new char[256][256]; // all "english" letters will be below 256
//... fill it... e. g. lookup['A']['C'] = 'M';
char consensus = lookup['A']['C'];
A simple, fast solution is to use bitwise-OR.
At startup, initialize two tables:
A sparse 128-element table to map a nucleotide to a single bit. 'Sparse' means you only have to set the members that you'll use: the IUPAC codes in upper and lowercase.
A 16-element table to map a bitwise consensus to an IUPAC nucleotide code.
To get the consensus for a single position:
Use the nucleotides as indices in the first table, to get the bitwise representations.
Bitwise-OR the bitwise representations.
Use the bitwise-OR as an index into the 16-element table.
Here's a simple bitwise representation to get you started:
private static final int A = 1 << 3;
private static final int C = 1 << 2;
private static final int G = 1 << 1;
private static final int T = 1 << 0;
Set the members of the first table like this:
characterToBitwiseTable[ 'd' ] = A | G | T;
characterToBitwiseTable[ 'D' ] = A | G | T;
Set the members of the second table like this:
bitwiseToCharacterTable[ A | G | T ] = 'd';
Given that they are all unique symbols, I'd go for an Enum:
public Enum ConsensusSymbol
{
A("A"), // simple case
// ....
GTUC("B"),
// etc
// last entry:
AGCTU("N");
// Not sure what X means?
private final String symbol;
ConsensusSymbol(final String symbol)
{
this.symbol = symbol;
}
public String getSymbol()
{
return symbol;
}
}
Then, when you encounter a difference, use .valueOf():
final ConsensusSymbol symbol;
try {
symbol = ConsensusSymbol.valueOf("THESEQUENCE");
} catch (IllegalArgumentException e) { // Unknown sequence
// TODO
}
For instance, if you encounter GTUC as a String, Enum.valueOf("GTUC") will return the GTUC enum value, and calling getSymbol() on that value will return "B".
The possible combinations are around 20. So there is not a real performace issue.
If you do not wish to do a big if else block, the fastest solution would be to build a Tree data structure. http://en.wikipedia.org/wiki/Tree_data_structure. This is the fastest way to do what you want to do.
In a tree, you put all the possible combinations and you input the string and it traverses the tree to find the longest matching sequence for a symbol
Do you want an illustrated example?
PS: All Artificial Intelligence softwares uses the Tree apporach which is the fastest and the most adapted.
Considered reading multiple sequences at once - I would:
put all characters from the same position in the sequence to a set
sort and concatenate values in the set and use enum.valueOf() as in fge's example
acquired value use as a key to a EnumMap having consesus symbols as a values
There are probably ways hot o optimize the second and the first steps.
A possible solution using enums, inspired by pablochan, with a little input from biostar.stackexchange.com:
enum lut {
AA('A'), AC('M'), AG('R'), AT('W'), AR('R'), AY('H'), AK('D'), AM('M'), AS('V'), AW('W'), AB('N'), AD('D'), AH('H'), AV('V'), AN('N'),
CA('M'), CC('C'), CG('S'), CT('Y'), CR('V'), CY('Y'), CK('B'), CM('M'), CS('S'), CW('H'), CB('B'), CD('N'), CH('H'), CV('V'), CN('N'),
GA('R'), GC('S'), GG('G'), GT('K'), GR('R'), GY('B'), GK('K'), GM('V'), GS('S'), GW('D'), GB('B'), GD('D'), GH('N'), GV('V'), GN('N'),
TA('W'), TC('Y'), TG('K'), TT('T'), TR('D'), TY('Y'), TK('K'), TM('H'), TS('B'), TW('W'), TB('B'), TD('D'), TH('H'), TV('N'), TN('N'),
RA('R'), RC('V'), RG('R'), RT('D'), RR('R'), RY('N'), RK('D'), RM('V'), RS('V'), RW('D'), RB('N'), RD('D'), RH('N'), RV('V'), RN('N'),
YA('H'), YC('Y'), YG('B'), YT('Y'), YR('N'), YY('Y'), YK('B'), YM('H'), YS('B'), YW('H'), YB('B'), YD('N'), YH('H'), YV('N'), YN('N'),
KA('D'), KC('B'), KG('K'), KT('K'), KR('D'), KY('B'), KK('K'), KM('N'), KS('B'), KW('D'), KB('B'), KD('D'), KH('N'), KV('N'), KN('N'),
MA('M'), MC('M'), MG('V'), MT('H'), MR('V'), MY('H'), MK('N'), MM('M'), MS('V'), MW('H'), MB('N'), MD('N'), MH('H'), MV('V'), MN('N'),
SA('V'), SC('S'), SG('S'), ST('B'), SR('V'), SY('B'), SK('B'), SM('V'), SS('S'), SW('N'), SB('B'), SD('N'), SH('N'), SV('V'), SN('N'),
WA('W'), WC('H'), WG('D'), WT('W'), WR('D'), WY('H'), WK('D'), WM('H'), WS('N'), WW('W'), WB('N'), WD('D'), WH('H'), WV('N'), WN('N'),
BA('N'), BC('B'), BG('B'), BT('B'), BR('N'), BY('B'), BK('B'), BM('N'), BS('B'), BW('N'), BB('B'), BD('N'), BH('N'), BV('N'), BN('N'),
DA('D'), DC('N'), DG('D'), DT('D'), DR('D'), DY('N'), DK('D'), DM('N'), DS('N'), DW('D'), DB('N'), DD('D'), DH('N'), DV('N'), DN('N'),
HA('H'), HC('H'), HG('N'), HT('H'), HR('N'), HY('H'), HK('N'), HM('H'), HS('N'), HW('H'), HB('N'), HD('N'), HH('H'), HV('N'), HN('N'),
VA('V'), VC('V'), VG('V'), VT('N'), VR('V'), VY('N'), VK('N'), VM('V'), VS('V'), VW('N'), VB('N'), VD('N'), VH('N'), VV('V'), VN('N'),
NA('N'), NC('N'), NG('N'), NT('N'), NR('N'), NY('N'), NK('N'), NM('N'), NS('N'), NW('N'), NB('N'), ND('N'), NH('N'), NV('N'), NN('N');
char consensusChar = 'X';
lut(char c) {
consensusChar = c;
}
char getConsensusChar() {
return consensusChar;
}
}
char getConsensus(char a, char b) {
return lut.valueOf("" + a + b).getConsensusChar();
}