Chronologiczne wyciąganie elementów z tablic

0

Siema

Mam taki oto z pozoru prosty fragment kodu, jednak trochę nerwów przy nim straciłem. Mam 4 tablice - 2 z czasami oraz 2 z wielkościami które im odpowiadają które dodaje/odejmuje do zmiennej buffer_size.

public class Main {

	public static void main(String[] args) {
		
		double[] input_time = {1.1, 1.3, 1,5, 1,7};
		double[] output_time = {1.2, 1.4, 1.6, 1,8};
	
		int[] input_size = {100, 10, 10, 20};
		int[] output_size = {10, 50, 10, 30}; //na koniec musi byc 40
		
		Buffer buffer = new Buffer();
		
		buffer.analysis(input_time, output_time, input_size, output_size);
		buffer.check();
	}

}

public class Buffer {

	int buffer_size=0;

	public void analysis(double[] input_time, double[] output_time, int[] input_size, int[] output_size) {
		
		for (int i = 0; i < input_size.length; i++) {
			
			for (int j = 0; j < output_size.length; j++) {
			
				
				if (input_time[i] < output_time[j]) {
					buffer_size = buffer_size + input_size[i];		
					break;
					}
				
					if (input_time[i] > output_time[j]) {
					buffer_size = buffer_size - output_size[j];	
					break;
					}
				}
		}
		System.out.println("buffer size: "+buffer_size);
	}

Analizując przebieg pętli znalazłem(mam nadzieję) miejsce z błędem:

  • dla i=0 -> j=0 dodaje do bufora
  • dla i=1 -> j=0 odejmuje z bufora
  • dla i=2 ->j=0 odejmuje z bufora - i tutaj właśnie moja pętla zaczyna wariować, dochodzi do momentu w którym porównuje input_time=1,5s do output_time=1,2s, a wartość z output[0] została już użyta.

Jak mogę wyeliminować błąd obliczeń na wartościach które były już wykorzystywane? Jak się nie mylę to zwykłe kasowanie każdego elementu tablicy po dodaniu/odjęciu spowoduję, że pętla też nie przejdzie poprawnie. Z jakiej kolekcji muszę skorzystać zamiast tablic?

0

Jak dołączysz biblioteke VAVR to będziesz miał prosto:

import io.vavr.Tuple2;
import io.vavr.collection.List;
//[...]
 public int analysis(double[] input_time, double[] output_time, int[] input_size, int[] output_size) {
        final List<Tuple2<Double, Integer>> inputs = List.ofAll(input_time).zip(List.ofAll(input_size));
        final List<Tuple2<Double, Integer>> outputs = List.ofAll(output_time).zip(List.ofAll(output_size));

        final List<Tuple2<Double, Integer>> ioEvents = inputs.appendAll(outputs.map(x -> x.map2(val -> -val)));
        final List<Tuple2<Double, Integer>> sorted = ioEvents.sortBy(event -> event._1);
        return sorted.foldLeft(0, (v, event) -> v + event._2);
    }
//[...]

Chociaż tak naprawdę to tylko zgaduję co chcesz zrobić. Bo patrząc po kodzie programu to sprawa upraszcza się do zsumowania dwóch tablic intów (nie widać po co są czasy podane).

Biblioteka VAVR to dobre kolekcje o ile masz te tablice wielkości do kilku tysięcy(*). Powyżej powoli zaczyna się robić overkill trzymania intów w kolekcjach ( i do tego niemutowalnych).
Pytanie gdzie tego zamierzasz użyć (w pewnych zastosowaniach nawet trzymanie 500 elementów int w io.vavr.collection.List<Integer> to już będzie przesada). W innych przypadkach możesz sobie nawet miliony trzymać i będzie git.

0

Robię projekt w którym przeprowadzam analize ruchu sieciowego pcap. Sprawdzam stan bufora (ile razy bufor był pusty, ile razy wyjęcie danych się nie powiodło, czas przez jaki bufor był pusty oraz rozmiar końcowy bufora).
Docelowo metoda analysis ma chronologicznie pod względem czasu input/output_time dodawać lub odejmować input/output_size (jeśli pakiet jest wychodzący to odejmuje z bufora, analogicznie do niego do dodaje jeśli wchodzi do bufora), dane te sprawdzam w pętlach,
Tutaj wkleiłem metodę z klasy testowej, w głównej mam bardziej złożony algorytm do sprawdzenia 3000 pakietów, a problem jest na pewno w tym, że program bierze pod uwagę kilkukrotnie jeden element zamiast go wymazać po wykorzystaniu więc wystarczy tylko operacja dodań/usuń

0

@lobuz_m: Zakładam, że nie musisz tego robić w czasie rzeczywistym, albo zbliżonym do rzeczywistego.

Mam 4 tablice - 2 z czasami oraz 2 z wielkościami które im odpowiadają które dodaje/odejmuje do zmiennej buffer_size.

Zastąpmy to na początek dwoma tablicami, które przechowują pary <czas, wartość>. Pary te można nawet sobie prezentować jako obiekty:

class In{
	final double time;
	final int value;

	public In(double time, int value) {
		this.time = time;
		this.value = value;
	}
}

class Out{
	final double time;
	final int value;

	public Out(double time, int value) {
		this.time = time;
		this.value = value;
	}
}

I dalej jak opisuje @jarekr000000. A i najważniejsze napisz te testy w jakiś sensowny sposób dzieląc je na mniejsze elementy algorytmu.

0

dotarlem chyba do jakiejs sciany bo mimo waszych podpowiedzi nie potrafię ruszyć dalej, stworzyłem hashmape <Double, Integer> i przypisuje wartosci do klucza(czasu) , ale przekazujac je do metody nie moge porownac kluczy metoda in.keys();
@jarekr000000 niestety co do bibilioteki vavr nie umiem w tym momencie z niej skorzystac

public class Main {

	public static void main(String[] args) {
		
		
		Map<Double, Integer> in = new HashMap<Double, Integer>();
		in.put(1.1, 100);
		in.put(1.3, 10);
		in.put(1.5, 10);
		in.put(1.7, 20);
		
		Map<Double, Integer> out = new HashMap<Double, Integer>();
		out.put(1.2, 10);
		out.put(1.4, 50);
		out.put(1.6, 10);
		out.put(1.8, 30);

        Buffer buffer = new Buffer();
 
        buffer.analysis(in, out);
       
    }

	class In{
	    final double time;
	    final int value;
	 
	    public In(double time, int value) {
	        this.time = time;
	        this.value = value;
	    }
	}
	 
	class Out{
	    final double time;
	    final int value;
	 
	    public Out(double time, int value) {
	        this.time = time;
	        this.value = value;
	    }
	}
	
	}

@jarekr000000 i @Koziołek
moge prosic o wiecej cierpliwosci i podpowiedz jakie dokladnie nastepne kroki musze wykonac?

0

Dla tych założeń

la i=0 -> j=0 dodaje do bufora
dla i=1 -> j=0 odejmuje z bufora
dla i=2 ->j=0 odejmuje z bufora - i tutaj właśnie moja pętla zaczyna wariować, dochodzi do momentu w któr....
nie bardzo chce mi wyjść 40, wychodzi 30 (rozpisane poniżej).

i = 0
j = 0
buffor = 0
		
input_time = {|1.1|, 1.3, 1.5, 1.7}
output_time = {|1.2|, 1.4, 1.6, 1.8}
		
input_size = {|100|, 10, 10, 20}
output_size = {10, 50, 10, 30}

1.1 < 1.2 -> buffor + 100

---

i = 1
j = 0
buffor = 100
		
input_time = {1.1, |1.3|, 1.5, 1.7}
output_time = {|1.2|, 1.4, 1.6, 1.8}
		
input_size = { _, 10, 10, 20}
output_size = {|10|, 50, 10, 30}

1.3 > 1.2 -> buffor - 10

---

i = 2
j = 1
buffor = 90
		
input_time = {1.1, 1.3, |1.5|, 1.7}
output_time = {1.2, |1.4|, 1.6, 1.8}
		
input_size = { _, 10, 10, 20}
output_size = {_, |50|, 10, 30}

1.5 > 1.4 -> buffor - 50

---

i = 3
j = 2
buffor = 40
		
input_time = {1.1, 1.3, 1.5, |1.7|}
output_time = {1.2, 1.4, |1.6|, 1.8}
		
input_size = { _, 10, 10, 20}
output_size = {_, _, 10, 30}

1.7 < 1.6 -> buffor - 10

---

buffor = 30

Żeby tak to działało wystarczy zrobić coś na tej zasadzie:

public void analysis(final double[] input_time, final double[] output_time, final int[] input_size, final int[] output_size) {
		for (int i = 0; i < input_size.length; i++) {
			for (int j = 0; j < output_size.length; j++) {
				
				if (input_time[i] < output_time[j]) {
					this.buffer_size = this.buffer_size + input_size[i];
					break;
				}
				
				if (input_time[i] > output_time[j] && output_size[j] != 0) {
					this.buffer_size = this.buffer_size - output_size[j];
					output_size[j] = 0;
					break;
				}
			}
		}
	}

Jest to bardzo brzydkie rozwiązanie bo zmienia wewnętrzny stan tablicy, więc de facto nie możesz jej użyć nigdzie indziej, ale jeżeli interesuje Cię jedynie stan tego buffera powinno wystarczyć.

Ps. Wybacz że rozbite na 2 posty, przypadkowy Enter zapisał posta.

//edited by @Koziołek: jak dobrze, że mamy moderatorów

1 użytkowników online, w tym zalogowanych: 0, gości: 1