Chronologiczne wyciąganie elementów z tablic

Chronologiczne wyciąganie elementów z tablic
LM
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 7 lat
  • Postów:4
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.

Kopiuj
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?

edytowany 1x, ostatnio: flowCRANE
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

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

Kopiuj
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.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 6x, ostatnio: jarekr000000
LM
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 7 lat
  • Postów:4
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ń

Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
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:

Kopiuj
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.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
LM
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 7 lat
  • Postów:4
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

Kopiuj
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?

Koziołek
zamień mapę na listę obiektów In/Out. Będzie ci łatwiej to używać. Double traci precyzję i może powodować dziwne zachowania.
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).

Kopiuj
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:

Kopiuj
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

edytowany 2x, ostatnio: Koziołek
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)