konto usunięte

Temat: Zagadka/i ;)

Tak na rozluźnienie atmosfery możemy sobie w tym temacie rozwiązywać zagadki programistyczne :)

Zacznę może ja:

Mamy trylionową tablicę jednowymiarową intów, jak sprawdzić czy w niej jest jakaś para liczb która daję jakąś konkretną sumę?

np może być taka sygnatura:

bool jestSuma(int* tablica, int szukana);

W czasie O(n) :)
Mateusz Herych

Mateusz Herych Arch Linux TU,
Student PK

Temat: Zagadka/i ;)

Ciekawe. :) Wpadłem na taki pomysł:


const int r = 7; // rozmiar, pozwolicie chyba, że nie podstawię tutaj tryliona

int t2[1024]; // zakładam, że nie będziemy szukać większych.
int t3[r];

bool jestSuma(int t[], int sz) {
for(int l=0;l<r;l++) {
if(sz-t[l]>0) {
t2[sz-t[l]]++;
t3[l]=(sz-t[l]);
}
}
for(int l=0;l<r;l++) {
if(t2[t[l]] && (t3[l]!=t[l] || t2[t[l]]>1)) return true;
}
return false;
}
Mateusz Herych edytował(a) ten post dnia 22.09.10 o godzinie 04:28
Jakub L.

Jakub L. Programista

Temat: Zagadka/i ;)

Pójdę na łatwiznę - skoro mamy trylionowa tablicę, to możemy zrobić sobie inną tak długą jak zakres inta?

konto usunięte

Temat: Zagadka/i ;)

Jakub L.:
Pójdę na łatwiznę - skoro mamy trylionowa tablicę, to możemy zrobić sobie inną tak długą jak zakres inta?

Dobrze kombinujesz ;)
Rozwiązanie oparte o hashset jest poprawne.

Dobra Panowie, wrzucajmy sobie co trochę w tym temacie jakieś podobne ciekawe pytania :)
Jakub L.

Jakub L. Programista

Temat: Zagadka/i ;)

Karim A.:
Jakub L.:
Pójdę na łatwiznę - skoro mamy trylionowa tablicę, to możemy zrobić sobie inną tak długą jak zakres inta?

Dobrze kombinujesz ;)
Rozwiązanie oparte o hashset jest poprawne.

Nie myślałem o haszsecie tylko o zwykłej zajebiaszczej tablicy.
Za każdym razem jak czytamy liczbę, wstawiamy true do tej tablicy w indeksie równym tej liczbie oraz sprawdzamy liczbę dopełniającą tę odczytaną liczbę do szukanej.
Jerzy Wierzchowski

Jerzy Wierzchowski Senior Software
Developer

Temat: Zagadka/i ;)

Zwykła tablica zajmuje jeden spójny obszar pamięci. Ciężko będzie znaleźć w RAMie miejsce na to chyba.
Jakub L.

Jakub L. Programista

Temat: Zagadka/i ;)

Dlatego się pytałem czy się da, skoro mamy trylionową tablicę.
Marek Dąbek

Marek Dąbek Software Engineer,
Intel Technology
Poland

Temat: Zagadka/i ;)

Jerzy Wierzchowski:
Zwykła tablica zajmuje jeden spójny obszar pamięci.

Niekoniecznie i im większa tablica tym bardziej powyższe jest nieprawdziwe ;)

konto usunięte

Temat: Zagadka/i ;)

Marek Dąbek:
Jerzy Wierzchowski:
Zwykła tablica zajmuje jeden spójny obszar pamięci.

Niekoniecznie i im większa tablica tym bardziej powyższe jest nieprawdziwe ;)

Pod względem logicznym jednak prawdziwe; segmentacja załatwia możliwość niespójności fizycznego obszaru pamięci. Czy ja nie wiem o jakimś innym mechanizmie?
Marek Dąbek

Marek Dąbek Software Engineer,
Intel Technology
Poland

Temat: Zagadka/i ;)

Aleksander W.:
Marek Dąbek:
Jerzy Wierzchowski:
Zwykła tablica zajmuje jeden spójny obszar pamięci.

Niekoniecznie i im większa tablica tym bardziej powyższe jest nieprawdziwe ;)

Pod względem logicznym jednak prawdziwe; segmentacja załatwia możliwość niespójności fizycznego obszaru pamięci. Czy ja nie wiem o jakimś innym mechanizmie?

Chodziło mi oczywiście o pamięć fizyczną. Zgadzam się, że mając adresy wirtualne tablica wygląda na ciągły obszar pamięci.

konto usunięte

Temat: Zagadka/i ;)

Marek Dąbek:
Aleksander W.:
Marek Dąbek:
Jerzy Wierzchowski:
Zwykła tablica zajmuje jeden spójny obszar pamięci.

Niekoniecznie i im większa tablica tym bardziej powyższe jest nieprawdziwe ;)

Pod względem logicznym jednak prawdziwe; segmentacja załatwia możliwość niespójności fizycznego obszaru pamięci. Czy ja nie wiem o jakimś innym mechanizmie?

Chodziło mi oczywiście o pamięć fizyczną. Zgadzam się, że mając adresy wirtualne tablica wygląda na ciągły obszar pamięci.

Z tą alokacją to różnie bywa (OS, x64, PAE, fragmentacja).

http://bit.ly/c5RTd2
http://bit.ly/d2ZmR8

konto usunięte

Temat: Zagadka/i ;)

Jerzy Wierzchowski:
Zwykła tablica zajmuje jeden spójny obszar pamięci. Ciężko będzie znaleźć w RAMie miejsce na to chyba.

Powiem więcej: ciężko będzie znaleźć taki RAM.
Zakładając 4 bajtowy int i wspomniany trylion mamy:
log2(4* 1 000 000 000 000 000 000 ) = ~62
2^62 to okolo 4.5 × 10^18

4.5 exabajta. Nice...
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: Zagadka/i ;)

Oj, Panowie, czepiacie się nieistotnych szczegółów.

Wystarczy sformułować zadanie inaczej:

<zadanie>
Czytamy ciągły strumień bajtów.
I teraz do wyboru:
a. Należy znaleźć i podać dwa bajty z tego strumienia, których suma wynosi X.
b. Należy znaleźć i podać pozycję dwóch bajtów w tym strumieniu, których suma wynosi X.
Wyszukanie ma zostać wykonane w czasie liniowym.
</zadanie>

I teraz już chyba problem pamięci nie jest istotny, prawda?

konto usunięte

Temat: Zagadka/i ;)

Piotr Głudkowski:
Oj, Panowie, czepiacie się nieistotnych szczegółów.

Nieprawda. Akurat tutaj rozmiar ma znaczenie...
I teraz już chyba problem pamięci nie jest istotny, prawda?
W ten sposób można każde zadanie sprowadzić do prostszego a tu chodzi o poradzenie sobie także z ilością danych

konto usunięte

Temat: Zagadka/i ;)

Piotr Głudkowski:
Oj, Panowie, czepiacie się nieistotnych szczegółów.

Wystarczy sformułować zadanie inaczej:

<zadanie>
Czytamy ciągły strumień bajtów.
I teraz do wyboru:
a. Należy znaleźć i podać dwa bajty z tego strumienia, których suma wynosi X.
b. Należy znaleźć i podać pozycję dwóch bajtów w tym strumieniu, których suma wynosi X.
Wyszukanie ma zostać wykonane w czasie liniowym.
</zadanie>

I teraz już chyba problem pamięci nie jest istotny, prawda?

Jest - ponieważ jeśli mamy tyle pamięci, żeby zapamiętać obecność lub indeks wartości "sparowanych" to problem jest prosty. W skrajnym przypadku (bardzo duży zbiór wartości elementów ciągu) zadanie jest niewykonalne. Wystarczy ciąg, którego elementy są mniejsze od połowy największej wartości typu elementu, a oczekiwana suma to największa wartość typu elementu. Po drodze trzeba zapamiętać co najmniej tyle bitów (jeśli wskazujemy tylko "jest para"), ile ma liczność typu/2. Dla bajtów - nie ma sprawy. Dla int32_t - od biedy (jeśli nie pamiętać indeksów).

Dlatego w zadaniu musi być informacja o dostępnej dodatkowej pamięci i rozmiarze typu elementu. Inaczej to bez sensu.

konto usunięte

Temat: Zagadka/i ;)

Inne zadanie, moje ulubione z "Perełek oprogramowania" (jeśli ktoś czytał, to proszę nie podpowiadać, jeśli ktoś nie czytał - mam nadzieję, że zachęci do książki):

Z ciągu N elementów (nie mieszczącego się w pamięci, odcztywanego sekwencyjnie) wylosować w jednym przebiegu M elementów (M < N). Dostępny jest generator losowy o rozkładzie jednostajnym. Jako utrudnienie bądź podpowiedź powiem, że nie używamy żadnej dodatkowej pamięci.
Jakub L.

Jakub L. Programista

Temat: Zagadka/i ;)

Przyjmując, że identyfikator pozycji w ciągu jest mniejszy lub równy elementowi ciągu, oraz że mamy daną pamięc albo na identyfikatory, albo na M elementów, to najpierw generujemy identyfikatory, potem je sortujemy, potem odczytujemy ciąg i wybieramy te, których pozycję wylosowaliśmy.

konto usunięte

Temat: Zagadka/i ;)

Jakub L.:
Przyjmując, że identyfikator pozycji w ciągu jest mniejszy lub równy elementowi ciągu, oraz że mamy daną pamięc albo na identyfikatory, albo na M elementów, to najpierw generujemy identyfikatory, potem je sortujemy, potem odczytujemy ciąg i wybieramy te, których pozycję wylosowaliśmy.

Założenie było, że nie używamy dodatkowej pamięci. Dla ustalenia uwagi możemy przyjąć, że zarówno N jak i M jest większe od dostępnej pamięci. Wylosowane elementy wyprowadzamy do strumienia.

O ile pamiętam w oryginale chodziło o wylosowanie sporej (jak na pamięć ówczesnych komputerów) grupy z listy wszystkich abonentów (do celów statystycznych).

konto usunięte

Temat: Zagadka/i ;)

Przyznam, poniosło mnie z podkreślaniem wagi tego, że tablica jest duża i należy szukać rozwiązania liniowego. Niemniej jednak, fajną dyskusję sprowokowałem :)
Adam Borowiecki

Adam Borowiecki Programista,
analityk,
wdrożeniowiec,...

Temat: Zagadka/i ;)

Karim A.:
Przyznam, poniosło mnie z podkreślaniem wagi tego, że tablica jest duża i należy szukać rozwiązania liniowego. Niemniej jednak, fajną dyskusję sprowokowałem :)


Nic Cie nie poniosło. Rozwiazanie zagadki jest następujące.

zadana liczba : Suma
badany jest ciąg liczb na pod względem wiadomej Sumy

tworze zbior liczb do przechowywania wartosci które juz sie pojawily;
Na razie pusty.

(
ilosc mozliwych liczb calkowitych (w komputerze
oczywiscie) jest stala (i znana) wiec czas potrzebny
na odnalezienie liczby w zbiorze bedzie ograniczony
przez stałą
)

pobieram kolejną liczbe i zapisuje do zmiennej X

szukam dopelnienia do sumy (suma-X):

jest jest w zbiorze
to return true;
a jak nie nie
to dopisuje zapisuje badana liczbe do zbioru

i to wszystko

Złożoność:
- jeden przebieg - N
- max dwa poszukiwania w zbiorze - stała 2
- przeszukiwanie zbioru - stala lub ograniczona stalą

A w C++ to mniej więcej tak (alem nie kompilowal tego):

const int MAX = .... // rownie dobrze moge brac dane
int Dane[MAX]; // ze strumienia
int suma = ... // szukana suma

set<int> dotychczas_byly;


for (int ii=0; ii<MAX; i++) {
int X=Dane[ii];
if (dotychczas_byly.find(Suma-X) )
return true;
else
dotychczas_byly.insert(X);
}
return false; // przeszukalim i nieznalezlim;

UWAGA; jesli typ danych wejsciowych bedzie mial mala liczbnosc np. unsigned char, (czyli zajmowal malo bajtow) to jako zmienna zbiorowa mozna zastosowac tablice)

dla unsigned char:

bool dotychczas_byly[256];

for (int ii=0;i<256;i++)
dotychczas_byly=false;

Wtedy badanie i uzupelnianie zbioru b. wygladc:

if ( dotychczas_byly[Suma-x] )
return true;
else dotychczas_byla[x]=true;

Zliozonosc obliczeniowa STALA i mala!

P.S.

1. Świat algorytmów jest swiatem idealnym i dlatego pytanie o dostępne zasoby
uważam za nietakt :)
2. Jeśli kogoś nie zadowala pkt. 1 to małe zużycie pamięci może zrekompensować
złożonoscią obliczeniową albo na odwrót. W życiu jest zwykle cóś z cóś.

Następna dyskusja:

Kolejna zagadka algorytmicz...




Wyślij zaproszenie do