I have a 2D List of type Integer (ArrayList< List < Integer > >),
There are currently 177147 lists of integers.
I want to separate these into 243 different collections (Each collection having 729 lists of elements)
e.g. Array[0] -> Array[728] go into Collection[0]
...until
Array[176417] -> Array[177146] goes into Collection[242]
Should I rather use ArrayList<ArrayList<List<Integer>>>?
If so, how do I separate these items in this manner?
Iterate on the elements and add by slices to the new structure:
public void run() {
int SLICE = 729;
List<List<Integer>> list2d = new ArrayList<List<Integer>>();
// fill original list
List<List<List<Integer>>> list3d = new ArrayList<List<List<Integer>>>();
List<List<Integer>> partial = new ArrayList<List<Integer>>(SLICE);
for (List<Integer> list : list2d) {
partial.add(list);
if (partial.size() == SLICE) {
list3d.add(partial);
partial = new ArrayList<List<Integer>>(SLICE);
}
}
if (!partial.isEmpty()) {
list3d.add(partial);
}
}
for(int c = 0; c <= 242; c++)
{
for(int i = 0; i < 729; i++)
{
int position = (c * 729) + i;
Collection[c][i] = Array[position];
}
}
You might want to check my maths on the formula for position, but the idea is sound.
Related
I have got two arraylists :
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(5);
numbers.add(2);
numbers.add(0);
numbers.add(0);
numbers.add(8);
ArrayList<String> linkers = new ArrayList<>();
linkers.add("five");
linkers.add("two");
linkers.add("zero");
linkers.add("zero");
linkers.add("eight");
I need to sort the numbers list in ascending order and get the linkers list sorted in the same order.
Assuming there is a one-to-one mapping of the number to their name you can do it like so. Just sort the indices based on the list of numeric numbers. Then use those indices to get each list's values in the proper, sorted order. Here, I just print them to show the results.
List<Integer> indices = IntStream.range(0, numbers.size()).boxed()
.sorted(Comparator.comparing(numbers::get)).toList();
for (int i : indices) {
System.out.println(numbers.get(i) + " " + linkers.get(i));
}
prints
0 zero
0 zero
2 two
5 five
8 eight
They could be "sorted" as follows:
numbers = indices.stream().map(numbers::get).toList();
linkers = indices.stream().map(linkers::get).toList();
System.out.println(numbers);
System.out.println(linkers);
prints
[0, 0, 2, 5, 8]
[zero, zero, two, five, eight]
Parallel lists/arrays are trouble. Put corresponding elements into combined objects, then sort those.
import java.util.ArrayList;
import java.util.Comparator;
class Pair {
public int i;
public String s;
public Pair(int _i, String _s) {
i = _i;
s = _s;
}
}
class Test {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(5);
numbers.add(2);
numbers.add(0);
numbers.add(0);
numbers.add(8);
ArrayList<String> linkers = new ArrayList<>();
linkers.add("five");
linkers.add("two");
linkers.add("zero");
linkers.add("zero");
linkers.add("eight");
ArrayList<Pair> pairs = new ArrayList<>();
for (int i = 0; i < 5; i++) {
pairs.add(new Pair(numbers.get(i), linkers.get(i)));
}
pairs.sort(new Comparator<Pair>() {
public int compare(Pair a, Pair b) {
if (a.i == b.i) return 0;
else if (a.i < b.i) return -1;
else return 1;
}
});
for (int i = 0; i < 5; i++) {
System.out.println(pairs.get(i).s);
}
}
}
One possibility would be to group each number (int) with its name (String) in a class (Java < 15) or record (Java >= 15):
record NumberWithName(int value, String name) {
}
Then, for each pair of int and String from the two Lists, construct a Number-instance and add it to a new List numbersWithName:
List<Integer> values = List.of(5, 2, 0, 0, 8);
List<String> names = List.of("five", "two", "zero", "zero", "eight");
List<NumberWithName> numbersWithName = new ArrayList<>();
for (int index = 0; index < values.size(); ++index) {
numbersWithName.add(new NumberWithName(values.get(index), names.get(index)));
}
Finally, we sort this List with a corresponding Comparator and print the result:
numbersWithName.sort(Comparator.comparing(NumberWithName::value));
System.out.println(numbersWithName);
This produces the following output:
[NumberWithName[value=0, name=zero], NumberWithName[value=0, name=zero], NumberWithName[value=2, name=two], NumberWithName[value=5, name=five], NumberWithName[value=8, name=eight]]
A TreeMap should help here where your key is the integer and the value represents the string. TreeMap is directly sorted by the key.
I'm new at programming. I have to write a code, main requirements - user chooses the sorting method (one is already added, the second one I will add later), enters the amount of elements in the array, enters the elements and then the code sorts them. But it looks like the code only takes the last entered element and tries to sort it. What do I have to do to make it sort all entered elements?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("181RDB094 Līva Gundega Ermansone 1");
System.out.print("method:");
int M;
if (sc.hasNextInt())
M = sc.nextInt();
else {
System.out.println("input-output error");
sc.close();
return;
}
System.out.print("count:");
int count = sc.nextInt();
int[] masīvs = new int[count];
System.out.println("items:");
masīvs = new int[count];
for (int i = 0; i < count; i++) {
masīvs[i] = sc.nextInt();
}
System.out.println("result:");
if (M == 1) {
int[] b = new int[count];
int[] less = new int[count];
int[] equal = new int[count];
int k;
for (int i = 0; i < count; i++)
for (int j = 0; j < count; j++) {
if (masīvs[i] == masīvs[j]) {
equal[i] = i++;
} else if (masīvs[i] > masīvs[j]) {
less[i] = i++;
}
}
for (int i = 0; i < count; i++) {
k = less[i];
for (int j = 0; j < equal[i]; j++) {
b[k + j] = masīvs[i];
}
}
for (int i = 0; i < count; i++) {
masīvs[i] = b[i];
System.out.print(masīvs[i] + " ");
}
} else if (M == 2) {
} else {
System.out.println("input-output error");
return;
}
}
Sorry for the ugly code, it's just a draft.
Expected:
181RDB094 Līva Gundega Ermansone 1
method:1
count:4
items:
13
31
55
2
result:
55 31 13 2
Actual results:
181RDB094 Līva Gundega Ermansone 1
method:1
count:4
items:
13
31
55
2
result:
2 2 2 0
You can add a simple for loop after filling your array to check the contents. There, you can see that all entries are written into the array correctly.
This will output:
Array:13
Array:31
Array:55
Array:2
for (int i = 0; i < masīvs.length; i++) {
System.out.println("Array:" + masīvs[i]);
}
The sorting method you are following fixes a set of equal elements at their proper position by finding the no of elements less than those elements.
The problem in sorting lies in finding the no of elements less and equal to.
equal[i]++; instead of equal[i]=i++;
Similarly,
less[i]++; instead of less[i]=i++;
If you're using Java 8 or more recent, you may be able to use the ArrayList class (with the Integer class) instead of an 1D array (i.e. int[] var = new int[x]); it would allow you to use its sort(Comparator) method instead.
You would have to create a Comparator instance (lambda function, or anonymous) or an implementing class, unless you want to use the natural ordering of those.
It would give you something around those two lines:
ArrayList<Integer> var = new ArrayList<>();
and var.sort(); (assuming you use the natural ordering)
It might however be harder to manipulate at first, if you're new to the Java Collection Framework, so don't hesitate to ask questions.
P.S.: I might have misunderstood the code, so just tell me so I can fix my answer.
P.S.S.: Somewhat unrelated, and it's probably in your mind (ignore that part then), but I would recommend you to refactor that into much more smaller methods/functions.
I think that your code organization is very bad. It's easier to give you more correct solution, than count and fix your problem:
public class Foo {
public static void main(String... args) {
final BiFunction<int[], Comparator<Integer>, int[]> sort =
(items, comparator) -> Arrays.stream(items)
.boxed()
.sorted(comparator)
.mapToInt(i -> i)
.toArray();
try (Scanner scan = new Scanner(System.in)) {
Comparator<Integer> comparator = getSortingMethod(scan);
int[] items = getItems(scan);
int[] sorted = sort.apply(items, comparator);
System.out.println(Arrays.toString(sorted));
}
}
private static final Comparator<Integer> SORT_ASC = Comparator.naturalOrder();
private static final Comparator<Integer> SORT_DESC = Comparator.reverseOrder();
private static final Comparator<Integer> SORT_NULL = (one, two) -> {
throw new IllegalArgumentException("input-output error");
};
private static Comparator<Integer> getSortingMethod(Scanner scan) {
System.out.println("181RDB094 Līva Gundega Ermansone 1");
System.out.print("method:");
try {
int M = scan.nextInt();
if (M == 1)
return SORT_DESC;
if (M == 2)
return SORT_ASC;
return SORT_NULL;
} catch(RuntimeException e) {
return SORT_NULL;
}
}
private static int[] getItems(Scanner scan) {
System.out.print("count:");
int[] items = new int[scan.nextInt()];
System.out.println("items:");
for (int i = 0; i < items.length; i++)
items[i] = scan.nextInt();
return items;
}
}
okay so we basically have this question to answer, but I am very confused and don't know how to use recursion to get all possible combinations.. Please someone save me!
Write a public static method threadings, which takes an int n (representing the number of beads on each necklace) and a Set of Strings (representing the available bead colours; your code must not alter this Set),and returns a Set of ArrayLists of Strings, representing all the orders in which n beads of the given colours can be threaded. If n < 1, return a Set containing just one, empty, ArrayList.
Examples of correct behaviour:
• threadings(0, {red,green}) = {[]}
• threadings(1, {red,green}) = {[red],[green]}
• threadings(2, {red,green})
= {[red,red],[red,green],[green,red],[green,green]}
• threadings(3, {red}) = {[red,red,red]}
Hint: you will probably want threadings to call itself recursively, although
full marks are available for any correct method.
This is what I have written until now:
public static HashSet<ArrayList<String>> threadings (int n, Set<String> colours){
HashSet<ArrayList<String>> result= new HashSet<ArrayList<String>>();
ArrayList<String> inresult= new ArrayList<String>();
String[] col= new String[colours.size()];
if (n==0){
result.add(inresult);
return result;
}else{
}
}
Try this:
public static HashSet<ArrayList<String>> threadings (int n, Set<String> colours) {
List<String> colorsList = new ArrayList<>(colours);
ArrayList<String> resultList = new ArrayList<>();
HashSet<ArrayList<String>> result = new HashSet<ArrayList<String>>();
int carry;
int[] indices = new int[n];
do
{
for(int index : indices) {
resultList.add(colorsList.get(index));
}
result.add(resultList);
resultList = new ArrayList<>();
carry = 1;
for(int i = indices.length - 1; i >= 0; i--)
{
if(carry == 0)
break;
indices[i] += carry;
carry = 0;
if(indices[i] == colorsList.size())
{
carry = 1;
indices[i] = 0;
}
}
}
while(carry != 1);
return result;
}
I have a list of lists:
List<List<String>> someList = new List<List<>>();
The maximum size of a list is five strings. It's something like below:
someList.get(0).size(); // 4 elements
someList.get(1).size(); // 1 elements
someList.get(2).size(); // 3 elements
someList.get(3).size(); // 1 elements
...
I'm trying to devise a method to create a new list of a specific size (1-5 elements) by combining some of the above nested lists. I could do something like the below (in this example, three elements):
public List<String> getThree() {
for (int j = 0; j < someList.size(); j++) {
//look for nested lists of size 3
if (someList.get(j).size() == 3) {
return someList.get(j);
}
for (int j = 0; j < someList.size(); j++) {
//if found nested list of size 2, find one of size 1 to combine
if (someList.get(j).size() == 2) {
for (int k = 0; k < someList.size(); k++) {
if (someList.get(k).size() == 1) {
return someList.get(j).add(someList.get(k).get(0));
}
}
}
for (int j = 0; j < someList.size(); j++) {
//if found nested list of size 1, find one of size 2 to combine
if (someList.get(j).size() == 1) {
for (int l = 0; l < someList.size(); l++) {
if (someList.get(l).size() == 2) {
return someList.get(j).addAll(someList.get(l));
}
}
}
}
}
I haven't included the loop for if no sublists are of size 2, to find three of size 1, but you can imagine how long and how ugly it can get. The order is important, thus the for loops incrementing sequentially (ie. I'd rather combine subList 1 + 2 more than 2 + 3, 1 + 3 more than 2 + 3, etc).
I'm hoping to find a way to dynamically implement this. I can only fathom how unreadable and long the getFive method will be provided my current methodology. I have multiple methods (getOne through getFive), it doesn't need to be dynamic in this sense, I'd just like to get rid of a lot of the if/else and for loops to reduce complexity and improve readability.
I should mention this is homework related, so I don't quite want a specific answer, but a nudge in the right direction. Something modulo perhaps? To do with remainders?
edit; to clarify and give an example:
aList = new List<String>;
aList.add("a");
aList.add("b");
someList.add(aList);
bList = new List<String>;
bList.add("c");
someList.add(bList);
newList = someList.getThree();
//newList.size() == 3
//newList contains "a","b","c"
The getThree() method is creating a new list comprised of elements from the sublists of someList. It cannot split a sublist (ie. it can't take 1 element from a sublist of 2 elements), it's combining whole sublists.
If your intention is to keep collecting from successive lists until you get 5 elements, keep adding then break out when your list is full:
public static List<String> fill(List<List<String>> sources, int size) {
List<String> list = new ArrayList<>();
for (List<String> source : sources)
if (source.size() <= size - list.size())
list.addAll(source);
return list;
}
If you want to consume the largest lists first, add this line as the first line of the method:
Collections.sort(sources, (a, b) -> b.size() - a.size());
In java 8, quite succinct:
public static List<String> fill(List<List<String>> sources, int size) {
return sources.stream().reduce(new ArrayList<>(),
(a, b) -> {if (b.size() <= a.size() - size) a.addAll(b); return a;});
}
and with the largest-first mod:
public static List<String> fill(List<List<String>> sources, int size) {
return sources.stream()
.sorted((a,b) -> b.size() - a.size())
.reduce(new ArrayList<>(), (a, b) ->
{if (b.size() <= a.size() - size) a.addAll(b); return a;});
}
Since you state that the priority of combining Lists is from left to right. An O(N^2) loop is sufficient to handle combining sublists to be less than or equal to your desired amount.
public static void main(String[] args) throws Exception {
List<List<String>> someList = new ArrayList() {{
add(new ArrayList() {{
add("a1");
add("a2");
}});
add(new ArrayList() {{
add("b1");
}});
add(new ArrayList() {{
add("c1");
add("c2");
add("c3");
}});
add(new ArrayList() {{
add("d1");
}});
}};
combine(someList, 4);
for(List<String> subList : someList) {
System.out.println(subList);
}
}
private static void combine(List<List<String>> someList, int combineAmount) {
for (int i = 0; i < someList.size(); i++) {
// Check if the current list already equals or exceeds the combineAmount
if (someList.get(i).size() >= combineAmount) {
continue;
}
// Add sublists to the current sublists until the size of the current
// sublist equals or exceeds the combineAmount
for (int j = i + 1; j < someList.size(); j++) {
if (someList.get(i).size() + someList.get(j).size() > combineAmount) {
continue;
}
someList.get(i).addAll(someList.get(j));
someList.remove(j);
j--;
// Don't bother checking other sublists if the newly
// combined sublists equals or exceeds the combineAmount
if (someList.get(i).size() >= combineAmount) {
break;
}
}
}
}
Results (combineAmount = 4):
[a1, a2, b1, d1]
[c1, c2, c3]
Results (combineAmount = 2):
[a1, a2]
[b1, d1]
[c1, c2, c3]
Results (combineAmount = 6):
[a1, a2, b1, c1, c2, c3]
[d1]
From what I understand you want to combine a list of lists into a total of 5 indexes. When doing this you want it to prioritize the left side first.
Here is a method I have created to do this. I know you did not want a specific example, but I think an example will help you understand as well as help others who also have this question:
private static List<String> getListOf(List<List<String>> someList, int size) {
List<List<String>> combine = new ArrayList<List<String>>();
List<List<String>> combinePrev = new ArrayList<List<String>>();
int value = 0;
int indexCloseValue = 0;
int indexClose;
for(int i = 0; i < someList.size(); i++){//Loops through the lists
value = someList.get(i).size();
boolean[] indexAdded = new boolean[someList.size()];//Used to make sure to not add duplicates
indexAdded[i] = true;
combine.add(someList.get(i));//add current loop to the combine list.
do{//A loop to try to add values other than the one of index i to equal size. This loops multiple times because it may take more than two to equal size.
indexCloseValue = 0;
indexClose = -1;
for(int j = 0; j < someList.size(); j++){
if(!indexAdded[j]){
int listSize = someList.get(j).size();
if(value + listSize > indexCloseValue && value + listSize <= size){
indexCloseValue = listSize;
indexClose = j;
}
}
}
if(indexClose == -1){
break;
}else{
combine.add(someList.get(indexClose));
value+=indexCloseValue;
indexAdded[indexClose] = true;
}
}while(value + indexCloseValue < size);
int added = 0;
for(List<String> str : combine){//Check size of combine list
added+=str.size();
}
int addedPrev = 0;
for(List<String> str : combinePrev){//Check size of combinePrev list
addedPrev+=str.size();
}
if(added > addedPrev && added <= size){
combinePrev = new ArrayList<List<String>>(combine);//Set combinePrev to combine if it is larger but less than size
}
combine = new ArrayList<List<String>>();//Reset combine
}
List<String> returnList = new ArrayList<String>();
for(List<String> list : combinePrev){//converts double list to a single list of strings at length "size".
for(String str : list){
returnList.add(str);
}
}
return returnList;
}
If there are any problems with this code or you have a question ask me in the comments.
List<Data> list = new ArrayList<Data>();
public class Data{
public int n;
public String p;
public Data(int N, String P) {
n = N;
p = P;
}
}
How can i shuffle the Integer of the Object: Data. So the String stays at the same position, and the Integer get's shuffled.
Loop through list and store the int of each Data object in a separate list. Shuffle this list using Collections.shuffle(...). Loop through this new shuffled list and set the n field of each corresponding member of list to the new random int found in the shuffled list.
Probably have to do it yourself:
for (int i = list.size(); i > 0; i--) {
int j = (int)(Math.random() * (i + 1));
int temp = list.get(i).n;
list.get(i).n = list.get(j).n;
list.get(j).n = temp;
}
The best you can do from java libraries is to first split it into two lists, one of ints and one of strings, then shuffle only the ints (using Collections.shuffle), then combine the two lists back into one list of Datas
You could use something like this:
List<Integer> ns = new ArrayList<Integer>(list.size());
for (Data data : list) {
ns.add(data.n);
}
Collections.shuffle(ns);
for (int i = 0; i < list.size(); i++) {
Data data = list.get(i);
int newN = ns.get(i);
data.n = newN;
}
Note that it's best practice to use accessors getN() and setN(int) and make Data.n private.