Operacje na tabelach wielowymiarowych

witam,
dopiero zaczynam przygodę z rubym, wcześniej pisałem w C++
czy mógłbym otrzymać jakieś wskazówki co do operacji na tablicach wielowymiarowych?
jak dodawać do nich kolejne wiersze? jak modyfikować konkretne pole?

probowałem pisać w stylu:

[code=ruby] puts “liczbe”
$jakas_tablica[0][0] = gets.to_i

     puts "podaj stan"
     tmp = gets.to_i
     $jakas_tablica[wiersz_tabeli,0] = tmp[/code]

niestety nie daje to dobrych wyników… ogólnie o tablicach wielowymiarowych znalazłem zadziwiająco mało informacji

Jest mało, bo tablic wielowymiarowych nie ma w Ruby, przynajmniej nie w taki sposób jak w C++. Tablice są obiektami, do których możesz wrzucać wszystko co chcesz, więc jeśli chcesz tablice wielowymiarową to musisz stworzyć zwykłą tablicę i wrzucać do niej także tablice.

[code=ruby]jakas_tablica = []
jakas_tablice[0] = []
jakas_tablica[0][0] = ‘cos’

puts jakas_tablica[0][0][/code]

czy w rubym indeksem tablicy może być zmienna? bez różnicy lokalna czy globalna?

Napewno programowales w c++ ?

Indeksem tabilicy jest integer, jesli zmienna bedzie zawierac integer to wszystko jest wpozadku, jesli nie parser zwroci blad. Jesli chcesz uzywac tablic asocjacyjnych masz do tego Hash.

btw rozumiem ze mialo byc:

[code=ruby] jakas_tablica = []
jakas_tablica[0] = []
jakas_tablica[0][0] = ‘cos’

  puts jakas_tablica[0][0][/code]

ale w ktorym miejscu nastepuje tu wrzucenie tablicy do tablicy?
tzn podejrzewam ze w drugiej linijce ale nie do konca wiem jak to zaszlo, do zerowego indeksu przypisalismy tablice?
jak by wygladalo dodanie kolejnego “wiersza”?

EDIT:
okej, troszkę tak z rozpędu to napisałem, już chyba rozumiem
BTW czym się sprawdza typ wartości trzymanej w zmiennej?

Krótka i zła odpowiedź: wyrażenie case lub metoda is_a?

Dłuższa i dobra: nie sprawdza się, program należy tak pisać, żeby nie było takiej potrzeby. Ruby jest językiem obiektowym i jeśli jesteś zmuszony do stosowania tablic wielowymiarowych to albo piszesz aplikację matematyczną (i Ruby nie do końca jest tu najlepszym wyborem) albo próbujesz pisać w sposób proceduralny. Lepszym rozwiązaniem jest stworzenie klas reprezentujących Twój model zamiast kilku metod działających na wspólnej wielowymiarowej tablicy.

Napisz co chcesz osiągnąć, co ma robić Twój program, podpowiemy Ci jak to zrobić na sposób Ruby.

heh, byłeś bardzo blisko poprawnej odpowiedzi
pisze aplikacje obsługującą deterministyczne automaty skończenie stanowe (troszkę matmy, troszkę logiki, języki formalne etc)
co do języka to mogłem wybrać dowolny pod warunkiem że to będzie Ruby :wink:
tablicy wielowymiarowej chciałem użyć jako wygodnej środka do przechowywania stanów i przejść

[quote=jjc]heh, byłeś bardzo blisko poprawnej odpowiedzi
pisze aplikacje obsługującą deterministyczne automaty skończenie stanowe (troszkę matmy, troszkę logiki, języki formalne etc)
co do języka to mogłem wybrać dowolny pod warunkiem że to będzie Ruby :wink:
tablicy wielowymiarowej chciałem użyć jako wygodnej środka do przechowywania stanów i przejść[/quote]
Podejście formalne z tablicą przejść i stanów słabo się tu sprawdzi. Lepiej w takim wypadku użyć obiektowości Ruby i odpowiedniego wzorca projektowego (http://en.wikipedia.org/wiki/State_pattern).

Jeśli możesz użyć Ruby on Rails to masz nawet gotowy plugin do implementowania maszyn stanów (http://agilewebdevelopment.com/plugins/acts_as_state_machine). Może służyć za wzór dla Twojej własnej implementacji choć jego wnętrze nie jest banalne (metaprogramowanie).

Z innych ciekawostek jest jeszcze Ragel (http://en.wikipedia.org/wiki/Ragel) który może wygenerować między innymi kod w Ruby, w tym również bazujący na tablicach.

Osobiście gdybym dawał tego typu zadanie to ostatnie rozwiązanie oceniłbym najwyżej :slight_smile:

hm… prowadzący chyba nie zna Rubiego, gdyby znał to chyba nie narzucił by go jako jedynego języka do wyboru
w sumie zadaniem jest udostępnienie samej klasy automatu w której należy umieścić:
funkcję do „budowania” automatu, uruchamiania go, oraz sprawdzenie czy akceptuje dany napis
i to wszystko dla minimum automatów deterministycznych
jak widać nie za bardzo jest pole do szczególnego popuszczenia wodzy fantazji
dodatkowo termin dość gardłowy- czego bardzo nie lubię,
gdyż z chęcią zapoznałbym się z bardziej zaawansowanymi zagadnieniami (wspomniane metaprogramowanie)

A te automaty mają służyć do wyszukiwania wzorców w tekstach? bo napisałeś, że automat ma akceptować napis. Jeśli tak to uważam, że nie powinieneś bawić się w żadne wzorce bo to za dużo zachodu.

hm… w sumie to jednym z elementów zadania jest zaakceptowanie napisu w formie np. aaabbc
(wcześniej ustala się reguły jak taki ciąg ma wyglądać), jednak mówienie że tylko o to tu chodzi jest chyba zbytnim spłyceniem tematu :wink:
BTW jednym z ciekawych elementów zadania jest to że można korzystać tylko z biblioteki standardowej…

Tak nie do końca rozumiem co masz na myśli, no ale nieważne. Do czego by nie służył ten automat to musi on mieć tą funkcję przejść, którą
chciałeś zaimplementować przy pomocy tablicy dwuwymiarowej. W Rubym myśle, że wygodniejsze będzie użycie tablicy Hashy wtedy będziesz mógł pisać coś takiego:

[code=ruby]tablica = []
tablica[0] = {}

tablica[0][‘b’] = 3
puts tablica[0][‘b’][/code]
gdzie pierwszy indeks to numer stanu a drugi to symbol wejściowy dla automatu. Jak skorzystasz z Hasha, to nie będziesz musiał się bawić w konwersje znaków na liczby.

Ja to opisuję z perspektywy wyszukiwania wzorców, ale to chyba jest uniwersalne.

Tak nie do końca rozumiem co masz na myśli[/quote]
łopatologicznie rzecz biorąc:
chodzi o to że najpierw należy zbudować automat (czyli jakby taki hm… schemat ciągu tekstowego),
później sprawdzić czy jest zbudowany dobrze (są określone zasady) a na koniec wrzucić w niego jakiś ciąg i zobaczyć czy “przechodzi”

dzięki za cenne wskazówki, rozumiem że Hash to po prostu tablica asocjacyjna?

gdyby ktoś jeszcze miał jakieś sugestie to chętnie posłucham :slight_smile:

Hash to tablica asocjacyjna ktore nie da sie posortowac. Przechwouje tylko indeks => wartosc, nie dba o kolejnosc indeksow.

Mnie też tak uczono. I trochę się zdziwiłem że od ruby1.9 będzie pamiętana kolejność kluczy. Teraz jednak uważam, że czasem może się to przydać :-).

Yup. A wiecej szczegolow tutaj http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l86 :stuck_out_tongue:

Witam,
Niestety tablice wielowymiarowe wciąż mnie nawiedzają, tym razem okazało się iż konieczne jest dodanie gdzieniegdzie “trzeciego wymiaru”
Wiem że rozwiązanie to nie jest najlepsze, jednak innego, z tych w miarę prostych, nie widzę
Mianowicie poniżej prezentuje kod metody budującej przejście, problemem jest to iż w komórce tablicy zawierającej informacje dokąd następuje przejście może znajdywać się więcej niż jedna wartość (co właśnie zmusza mnie do wrzucenia tam tablicy)
Niestety nie do końca wiem jak poradzić sobie z problemem ustalenia numeru indeksu dla kolejnego wrzucanego elementu
Poniższe źródło może wyjaśnić co nieco:

[code=ruby] def buduj_przejscie(skad,dokad,przejscie)

@tab_pis[pozycja_stanu(skad)][pozycja_przejscia(przejscie)] = Array.new

  @tab_pis[pozycja_stanu(skad)][pozycja_przejscia(przejscie)][0] = 1 #TYLKO TAK UMIEM WRZUCIC ELEMENT
  puts @tab_pis[pozycja_stanu(skad)][pozycja_przejscia(przejscie)][0]  #POZNIEJ LADNIE DA SIE GO WYDRUKOWAC

#@tab_pis[pozycja_stanu(skad)][pozycja_przejscia(przejscie)][] << dokad #CZY JAKOS W TEN SPOSOB MOGE OMINAC PODANIE NUMERU ELEMENTU?

end[/code]
__| a | b | eps

1 |2,3| |

2 | |1,2|

3 | | |

Od jakiegoś czasu można w Rubym robić tablicę następująco:
Array.new(10){ Array.new(10) }

Co tworzy tablicę 10x10.

W dowolnym elemencie możesz zamiast wartości wpakować kolejną tablicę, czyli - trzeci wymiar.

ok, to już wiem,
jednak nie wiem jak w metodzie dodawać kolejne elementy do tego “trzeciego” wymiaru (skąd brać numer indeksu dla tego elementu),
oraz gdzie zainicjować trzeci wymiar tak aby nie był tworzony wielokrotnie w danej komórce tablicy dwuwymiarowej

[code=ruby]a = nil
(a ||= []) << 1
p a

a = Array.new { [] }
a << 2
p a[/code]
Pick your favourite.