Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [php] etapowe rozwiązywanie działań
Forum PHP.pl > Forum > PHP
Stron: 1, 2
1010
Witam!
Potrzebuje napisać skrypt który będzie rozwiązywał działania i będzie przedstawiał etapy jego rozwiązania, np.
Podaje mu działanie:
6*4*(2/5+34-2*2)/2
a on wykonuje na nim operacje i zwraca mi takie coś:
6*4*(0,4+34-4)/2=
=6*4*34,4/2=
=24*34,4/2=
=24*17,2=
=417,6

Zdaję sobie z tego sprawę że to nie będzie proste zadanie, wiec prosze was o pomoc...

Jak się za taki skrypt zabrać?
Co proponujecie?
gszesiek
nie jestem specjalistą od algorytmów, ale może podaj mu kolejność wykonywania zadań, niech po każdej czynności pokazuje wyniki

ponieważ nie znam dodatkowych funkcji to raczej zrobiłbym to w ten sposób:
traktował każdy znak osobno (może w tabelę)
no i if-owanie:
jeśli cyfra koło cyfry to liczba
jeśli nawias to szuka jego końca
jeśli jakiś znak to porównuje go z innymi czy ma być pierwszy czy później (znaki możesz kolejno ustawić w tablicy)
.....
(kurcze dużo zabawy :|, jak znajdziesz coś mądrego, albo wymyślisz, to podziel się tym)
powodzenia
1010
hmm tylko jak mu ją podać... to wszystko chyba nie będzie takie proste...
Gnomik
Widzę to jako funkcję rekurencyjną, rozbijającą całość na coraz mniejsze elementy. Zawierałaby w sobie priorytet wykonywania działań i poczynając od nawiasów, kończąc na dodawaniu: wywoływałaby siebie dla coraz mniejszych elementów składowych całego wyrażenia. Na moje oko sprowadza się to do wyrażeń PEARowskich i operacji na łańcuchach.

Pozdrawiam,
Gnomik
1010
Więc jak od strony teoretycznej proponujecie to wykonać? Jakoś tak dokładniej... ?
Prph
Takimi rzeczami zajmuje sie informatyka teoretyczna winksmiley.jpg A podobne schematy naleza do dzialan automatow. Tak - ja tez tyle zrozumialem po wykladach.

Nie dam sobie reki uciac, ale w PHP5. Zaawansowane programowanie z Helionu byl fragment o jakiejs bibliotece do automatow skonczonych. Nie mam jej przy sobie, ale moze w ktos z forumowiczow skojarzy.

Tak, czy inaczej - bez gotowych algorytmow, to nie jest proste.

Adrian.
1010
Cytat
Tak, czy inaczej - bez gotowych algorytmow, to nie jest proste.

To akurat wiem... ale nie znaczy to że nie możliwe...

Krok po kroku powoli napewno da rade to zrobić...
s_w_ir
Na początku kilka pytań:
Czy to na pewno ma być w php(ważne!)?
Jak będzą wprowadzane działanie(<input ...>)?
Ile działań ma być obsługiwanych?
Jeśli jakieś inne niż 4 podstawowe to trzeba określić konwencje dla nich.

Ogólnie do zrobienia, ale trzeba wiedzieć te pare rzeczy.
1010
Cytat(s_w_ir @ 3.10.2006, 22:40:48 ) *
Na początku kilka pytań:
Czy to na pewno ma być w php(ważne!)?
Jak będzą wprowadzane działanie(<input ...>)?
Ile działań ma być obsługiwanych?
Jeśli jakieś inne niż 4 podstawowe to trzeba określić konwencje dla nich.

Ogólnie do zrobienia, ale trzeba wiedzieć te pare rzeczy.


1. Tak, ma to być w php
2. Działania będą wprowadzane poprzez <imput type=text> albo jakiś textarea ale to już chyba nie ma większego znaczenia
3. Poza tymi podstawowymi myslałem jeszcze nad pierwiastkami 2 i 3 stopnia, z tym że nie wiem jak je oznaczać w działaniu.
Gnomik
Bardzo uproszczony algorytm:

1. Wykryj obecnosc nawiasu (zawsze nadrzędnego w stosunku do reszty)
2. Jeśli stwierdzono w tej czesci obecnosc dodawania (+/-), rozdziel na lewą i prawą stronę
3. Sprawdź mnożenie i dzielenie - rozbij na lewą i prawą stronę

Oczywiście jeśli którykolwiek z tych punktów jest prawdziwy, wróć do punktu 1 i powtórz kroki dla wyciętego fragmentu.
s_w_ir
Hmm no to dalej jedziemy teorią, plan algorytmu:
0.Możemy potraktować wszystko jako string o ile php się nie uprze i tego za szybko nie wyliczy.
1.Szukamy wyrażenia ograniczenego nawiasami, uwzględniając wielkrotne nawiasy.
Jeśli się udało, to w odnaleziony ciągu powtarzamy 1 pkt do czasu gdy nie będzi już wyrażeń w nawiasach. 2.Operujemy na otrzymanym ciągu wykoując dziłania wedle priorytetów(pierwiastek, mnożenie/dzielenie,dodawanie/odejmowanie), wyświetlając po każdym wykonanym priorytecie wynik działania, czyli jeśli mamy np.: (8*5*6) to od razu otrzymamy z tego 240.
2 pkt powtarzamy aż do czasu gdy zostnie nam z danego nawiasu tylko jedna liczba(wynik).

Co do samego algorytmu to 1pkt regexpy, 2pkt regexpy smile.gif

Można się też bawić w stosy, czyli tak jak to naprawde jest liczone, tyle że wtedy możemy stracić możliwość wypisywania pośrednich wyników działań, a przynajmniej będzie trudniej.
1010
odnosnie tych nawiasów...
Kiedy już znajde że jest nawias... zapisuje sobie jego zawartosc do jakiejs zmiennej i w niej szukam dalej nawiasow.. itd? jak nazywac te zmienne, co robic ze zmienna gdzie mam cale rownanie, wstawiac jakies "X" czy coś?
Gnomik
Tutaj chyba z pomocą przyjdą wyrażenia PEAR'a. Ten temat jest dla mnie niestety jeszcze troszkę śliski, ale polecam się z nim zapoznać - bo chyba to będzie rozwiązaniem problemu z nawiasami. Nie ma sensu lecieć znak po znaku sprawdzając czy to jest nawias czy nie, jak można generalnie zwrócić wszystko co jest pomiędzy znakami ( ... ), [ ... ] czy jakichś innych (zupełnie jak w templatesach).
s_w_ir
Cytat
Kiedy już znajde że jest nawias... zapisuje sobie jego zawartosc do jakiejs zmiennej i w niej szukam dalej nawiasow.. itd?

Rekurencja Panie, rekurencja smile.gif Miejmy nadzije że obejdzie się bez ładowania tego w zmienne, ale jak coś mamy tablice(t[1],t[2]...)
Cytat
co robic ze zmienna gdzie mam cale rownanie, wstawiac jakies "X" czy coś?

Można by oznaczyć X fragment na którym aktualnie pracujemy żeby potem łatwo wstawić tam ostatni wyliczony fragment działania. Można też zapisywać pozycje od lewej początka i końca miejsca na którym operujemy.

Nie bawiłbym się w nawiasy [ i ( a tylko w ( gdyż łatwiej zapisać działanie,a róznorodnymi nawiasami ograniczmy się do np. 3 zagłębień.
1010
Tak czy siak coś z tym wyciągnietym nawiasem trzeba zrobić.
Gnomik
  1. <?php
  2. function rekmat($wyrazenie)
  3. {
  4. if(/*wyrazenie PEARa*/) rekmat(/*wyrazenie PEARa*/);
  5. else
  6. {
  7. if(strpos($wyrazenie, '-')!=0)
  8. {
  9. $strony = explode('-', $wyrazenie);
  10. rekmat($strony[0]);
  11. rekmat($strony[1]);
  12. }
  13. elseif(strpos($wyrazenie, '+')!=0)
  14. {
  15. $strony = explode('+', $wyrazenie);
  16. rekmat($strony[0]);
  17. rekmat($strony[1]);
  18. }
  19. else
  20. {
  21. if(strpos($wyrazenie, '/')!=0)
  22. {
  23. $strony = explode('/', $wyrazenie);
  24. rekmat($strony[0]);
  25. rekmat($strony[1]);
  26. }
  27. elseif(strpos($wyrazenie, '*')!=0)
  28. {
  29. $strony = explode('*', $wyrazenie);
  30. rekmat($strony[0]);
  31. rekmat($strony[1]);
  32. }
  33. }
  34. }
  35. }
  36.  
  37. ?>


To jest mniej więcej (bardziej mniej niż więcej) zapis zagłębiania sie w wyrażenie. Nie zawiera przeliczeń ani wyświetlania, ale to już kosmetyka...

W przypadku gdy bierzemy pod uwagę nawiasy [ ( {, stosowanie PEARa ma sens... Jeśli zostajemy przy samych ( to nie widze innego wyjścia niż krok po kroku sprawdzanie który ) zamyka nasz pierwszy (. To tez nie problem w sumie.

Pozdrawiam,
Gnomik
1010
ooo.. Dzięki bardzo za kod... Dziś po południu przeanalizuje go sobie... no i będę pracował dalej... potem przejdziemy do działań i predstawiania tego ładnie...

Pozdrawiam

Przeanalizowałem sobie tak ten kod... i musze zapytać
Gdzie tu jest jakis fragment uwzględniający jakieś nawiasy albo coś?
Gnomik
Tutaj worriedsmiley.gif :
  1. <?php
  2. if( /*wyrazenie PEARa*/ ) rekmat( /*wyrazenie PEARa*/ );
  3. ?>

Tak jak pisałem wczesniej - wyrażenia regularne to dla mnie bardzo śliski grunt.

  1. <?php
  2. if(preg_match("/(.*)", $wyrazenie)!=0) {  // a najlepiej ==1 
  3. $nawiasy = preg_split("/(.*)", $wyrazenie);
  4. rekmat($nawiasy[0]);
  5. }
  6. ?>

Tyle tylko że " /\(.*\) " niestety nie bierze pod uwagę wielu ewentualności, np. preg_split dla (4*5)-(5/2) zwróci 4*5)-(5-2 (oczywiście po odchudzeniu go z pierwszego i ostatniego znaku czyli ( ) )

Nad tym trzeba by pomyśleć. No i warunki lepiej powstawiać w tym kodzie (chyba sam if a nie elseif lepiej się sprawdzi...). Narazie jestem w pracy i nic nie mogę tutaj zrobić, ale jak wróce do domu to spróbuję napisac pełny kod tego czegoś... smile.gif

Pozdrawiam serdecznie,
Gnomik
eai
Jeśli działania będą proste czyli tylko znaki + - * / [ () ]
to można zrobić to etapowo. Bez wyrażeń regularnych się nie obejdzie.

1. Na początek jeśli występują nawiasy () [] liczysz ich ilość otwarte/zamkniete zeby sie wszystko zgadzalo
2. Potem wbierasz nawiasy w których nie ma innych nawiasów i wykonujesz działania mnożenia, dzielenia, i tyle przepisujesz reszte
3. Jeśli w nawiasie wszystko wymnozyles a sa jeszcze znaki + - to wykonujesz działania i przepisujesz reszte
4. Opuszczasz nawiasy gdzie nie ma juz znakow matematycznych
5. Wykonujesz dzialania teraz znowu mnozenia przepisujesz
6. Wykonujesz + -
i masz wynik

Teoretycznie tak to by wygladalo. I zaminiaj przecinki na kropki.

Trudne to nie jest, raczej czasochłonne przy robieniu funkcji parsującej.
1010
Cytat(eai @ 4.10.2006, 16:31:23 ) *
3. Jeśli w nawiasie wszystko wymnozyles a sa jeszcze znaki + - to wykonujesz działania i przepisujesz reszte

A co jeśli wynikiem jest liczba ujemna?
Trzeba ją zapisywać wtedy cały czas w nawiasie i zaczynają sie małe problemy...
eai
jeśli ujemna zapisujesz sobie je w specjalnym znaku np $-1$ przy wyswietlaniu mozesz zamieinic na nawiasy jesli tego potrzebujesz, ale generealnie trzymasz sobie w zmiennej jako $$ , ewentualnie jesli stoja obok siebie dwa znaki bez cyfry czyli -- lub +- to odrazu zamieniasz je na + lub -

Trzeba rozwazyc wszystkie przypadki jakie moga wystapic w dzialaniu.
1010
Okej.
Tak na rozgrzewke pisania tego od strony kodowej napisałem mini funkcje która sprawdza czy ilość nawiasów jest sobie równa. Oto ona:
  1. <?php
  2. function sprawdz_nawiasy($wyrazenie)
  3. {
  4.  //funkcja sluzy do sprawdzenia czy liczba otwarc nawiasow jest rowna
  5.  //liczbie zamkniec nawiasow, po to aby nie bylo niezamknietych nawiasow
  6.  
  7.  //rodzaje nawiasow:
  8.  //nawias1: "{"
  9.  //nawias2: "}"
  10.  //nawias3: "["
  11.  //nawias4: "]"
  12.  //nawias5: "("
  13.  //nawias6: ")"
  14.  
  15.  preg_match_all("/{/", $wyrazenie, $nawias1);
  16.  $nawias1 = count($nawias1[0]);
  17.  
  18.  preg_match_all("/}/", $wyrazenie, $nawias2);
  19.  $nawias2 = count($nawias2[0]);
  20.  
  21.  preg_match_all("/[/", $wyrazenie, $nawias3);
  22.  $nawias3 = count($nawias3[0]);
  23.  
  24.  preg_match_all("/]/", $wyrazenie, $nawias4);
  25.  $nawias4 = count($nawias4[0]);
  26.  
  27.  preg_match_all("/(/", $wyrazenie, $nawias5);
  28.  $nawias5 = count($nawias5[0]);
  29.  
  30.  preg_match_all("/)/", $wyrazenie, $nawias6);
  31.  $nawias6 = count($nawias6[0]);
  32.  
  33.  if($nawias1!=$nawias2)
  34.  {
  35. print "Liczba nawiasów "{" jest różna liczbie nawiasów "}".";
  36. return 0;
  37.  }
  38.  elseif($nawias3!=$nawias4)
  39.  {
  40. print "Liczba nawiasów "[" jest różna liczbie nawiasów "]".";
  41. return 0;
  42.  }
  43.  elseif($nawias5!=$nawias6)
  44.  {
  45. print "Liczba nawiasów "(" jest różna liczbie nawiasów ")".";
  46. return 0;
  47.  }
  48.  else
  49.  {
  50. return 1;
  51.  }
  52. }
  53. ?>

jeżeli macie jakieś propozycje odnośnie ulepszenia tej funkcji to oczywiście piszcie.

Odnośnie tych ujemnych liczb
to ma w wyrazeniu potem wygladac mniej wiecej tak:
36+3*$-1$:45 questionmark.gif
eai
Przykład: 2+ (45 - (23/100 * (34-36) ) ) + 4 + 7;

1. 2+ (45 - (23/100 * (34-36) ) ) + 4 + 7;
2. 2+ (45 - (23/100 * $-2$ ) ) + 4 + 7;
3. 2+ (45 - (0.23 * $-2$ ) ) + 4 + 7;
4. 2+ (45 - (0.23 * $-2$ ) ) + 4 + 7;
5. 2+ (45 - $- 46$ ) + 4 + 7;
6. 2+ 91 + 4 + 7;
7. 104;

Tak by wygladaly zmienne przechowywane w celu obliczania a do wyswietlania zamieniasz $$ na ()

Musisz sobie rozspisac wszystko na kartce i krok po kroku wymyslic schemat i zasade dzialania a potem bierz sie za przelanie tego na php
1010
Dokładnie... Dziś biore zeszyt na ten projekt i zabieram sie teoretycznie za myślenie nad tym projektem jak to dokładnie ma działać. Jak coś wyskrobie to wrzuce do tego tematu żebyście mogli to ocenić i ewentualnie coś poprawić... Pozdrawiam.
eai
Pomoge Ci teoretycznie.

Ogólnie całość trzeba zapętlić i każde etap zapisywać w tablicy.
jeśli wynik działania jest ujemny wstawiasz go w $$
$end = false

$math = '2+ (45 - (23/100 * (34-36) ) ) + 4 + 7';
while($end == false)
{
wczytanie zmiennej (string) z zadankiem czyli $math
Każdy etap to to samo.
1. Wybierasz tylko ten nawias gdzie nie występują znaki () : czyli do preg dajesz [^()]* lub wybierasz cały blok jeśli nie ma nawiasu.
2. Szukasz znaku mnożenia dzielenia jeśli są wykonujesz te działania i defniujesz zmienną pomocniczą $loose = true;
3. Jeśli loose == false szukasz znaków dodawania i odejmowania jeśli takie są wykonujesz działania i defniujesz $loose = true;
4. Jeśli $loose == false opuszczasz nawias pamietając że jeśli wynik ujemny stawiamy $$
5. Teraz sprawdzasz czy są jeszcze znaki dzielenia mnożenia lub nawiasy, jeśli nie ma dajesz $end = true. ale jeszcze dopisujesz caly blok to tablicy[]
6. Jesli doszlo do tego momentu to zapisujesz caly etap do tablicy[] i definujesz $math = na te co przeszlo te wszystkie zmiany powyzej.
// i tu petla sie skonczy i wczyta sie od nowa
}

taka pętla będzie się wykonywała tyle razy aż do końca całości.
To tylko takie teoretyczne założenia, musisz jeszcze sprawdzic czy nie wystapia jakies dziwne sytuacje gdzie ify sobie z tym nie proadza i petla bedzie w nieskonczonosc.

Ale ogolnie bym opieral sie na tym co napisalem rozbudowywujac kazdy element


Mam nadzieje ze troche rozjasnilem sprawe smile.gif
1010
Nom ogólnie schemat jest dobry...

Tylko teraz mam pytanie... jak wykonac dzialanie...

Powiedzmy ze mam juz wyciągnięty jakiś tam jeden całkiem środkowy nawias i wygląda on mniej więcej tak:
4+2*6
i znajduje w nim "*" czyli mnożenie... i teraz jak wykonac to dzialanie?
jak wyciagnac z tej calosci ta dwojke i 6 zeby wlasnie je ze soba pomnozyc...

I jeszcze jedno... co jeśli w tym przypadku 6 bedzie wygladala tak: $-6$ ? na ile zmienia się nam sytuacja? czy wystarczy wyrzucic $?

i jeszcze jedno... tongue.gif

zaczalem sie bawic pomalu od strony kodowej i mam takie cos:
  1. <?php
  2. function rozwiaz_dzialanie($wyrazenie)
  3. {
  4.  while($koniec==false)
  5.  {
  6. preg_match("/[^()]*/", $wyrazenie, $nawias);
  7. print_r ($nawias);
  8. $koniec=true;
  9.  }
  10. }
  11.  
  12. print rozwiaz_dzialanie("4+2*((344+3454)-2343(4342-434))*(43-43)");
  13. ?>

i problrem jest ze zamiast nawiasu zwraca mi wartosc z przed nawiasu czyli "4+2*"...

jak zrobic te wyrazenie?
UDAT
1. Skorzystaj z RPN do przetworzenia działania,
2. następnie wykonuj jedno działanie ( tzn. zdjęcie ze stosu 3 np.
  1. <?php
  2. eval ( '$wynik='.$drugi.$pierwszy.$trzeci;');
  3. dodaj_do_stosu ( $wynik );
  4. ?>

)
3. Potem poszukaj algorytmu przekształcania RPN na wyrażenie z priorytetami. Wynik wypisz ( skocz do 2 )
1010
Powiedzmy że chce przy tym algorytmie pominąć RPN... Pozdro
eai
  1. <?php
  2. if(eregi('(.*)',$wyrazenie))
  3. {
  4.  preg_match("/([^()]*)/", $wyrazenie, $nawias);
  5. }
  6. ?>


Jesli sa nawiasy to szuka nawiasu w ktorym nie ma drugiego nawiasu
1010
ok juz dziala...

zastanawiam sie teraz nad jedna rzecza... czy do rozwiazywania rownan juz bez nawiasow stworzyc osobna funkcje czy robic wszystko w tej jednej?

nom i stworzylem takie cos (a raczej wiecej skopiowalem) ze wyciaga ladnie nawias...

  1. <?
  2. function rozwiaz_dzialanie($wyrazenie)
  3. {
  4.  while($koniec==false)
  5.  {
  6. if(eregi('(.*)',$wyrazenie))
  7. {
  8.  preg_match("/([^()]*)/", $wyrazenie, $nawias);
  9.  //obcinamy nawiasy z wyciagnietego jednego nawiasu...
  10.  $nawias = substr($nawias[0], 1,-1);
  11.  
  12.  print $nawias;
  13.  
  14. }
  15. $koniec=true;
  16.  }
  17. }
  18.  
  19. print rozwiaz_dzialanie("4+(2*4342*4342)");
  20. ?>

i teraz taki problem...

Jez w zmiennej $wyrazenie zamiast tego nawiasu wstawic "x"?
Myslalem nad preg_replace ale jest problem... jak w nawiasie jest gwiazdka to nie lapie bo powinno byc tak: "4543\*564" zamiast "4543*564"?
Pozdro
cicik
Proponuję zainteresować się notacją Łukasiewicza inaczej zwaną Odwrotną Notacją Polską (ONP).
Jest to jedna z niewielu rzeczy wymyślonych przez Polaków, której używa się we współczesnych komputerach.
Algorytm przekształcenia wyrażenia zapisanego w tradycyjny sposób do ONP jest banalny (polega na użyciu stosu) i na pewno w google się go znajdzie. Jeżeli wyrażenie będzie zapisane w ONP to jego obliczenie też jest sprawą trywialną ponieważ ONP charakteryzuje się tym, że nie używa nawiasów więc po kolei wczytuje się dwa argumenty, znak działania, liczy się co trzeba i wynikiem zastępuje się pobrane dane. Do rozwiązywania działań zapisanych w ONP również używa się stosu. Tak bym to widział. Według mnie metoda najprostrza ii najłatwiejsza do zrealizowania w języku programowania (po to wymyślono ONP).
1010
Problem w tym że ja czytałem troche na ten temat i nie za bardzo rozumiem o co w tym wszystkim chodzi, tzn. jak z tego korzystać. Może udzielisz mi takiej pomocy...
cicik
Cytat(1010 @ 4.10.2006, 20:35:19 ) *
Problem w tym że ja czytałem troche na ten temat i nie za bardzo rozumiem o co w tym wszystkim chodzi, tzn. jak z tego korzystać. Może udzielisz mi takiej pomocy...


Jasna sprawa.

W tradycyjnym sposobie zapisywania działań jest pewna trudna sprawa - nawiasy i kolejność działań.
Cały bajer polega na skonstruowaniu systemu, w którym ich nie ma.

Mamy działanie:

4 * (2 + 8)

Obliczamy je następująco:

4 * (2 + 8) = 4 * 10 = 40

W progranmie trzeba wykrywać nawiasy, analizować kolejnośc wykonywania działań i takie tam.
W ONP zasada jest taka: zapisujemy argumenty działania, a po nich operator jaki na tych argumentach należy wykonać.

np: (po lewej zapis tradycyjny po prawej w ONP)

2 + 8 = 2 8 +
4 * 45 = 4 45 *
2 + 3 * 4 = 2 3 4 * +

Przykład z początku:

4 * (2 + 8) = 4 2 8 + *

Wyrażenie w ONP obliczamy następująco:

4 2 8 + * = 4 10 * = 40

Mam gdzieś w notatkach rozpisane schematy blokowe algorytmów do konwersji zapisu na notację ONP i do obliczania wyrażenia zapisanego w ONP. Jeśli google nie znajdzie (w co nie wierzę) to zeskanuję i gdzieś wywieszę. Ale wolałbym aby była to ostateczność.
UDAT
Cytat(cicik @ 4.10.2006, 20:30:38 ) *
Proponuję zainteresować się notacją Łukasiewicza inaczej zwaną Odwrotną Notacją Polską (ONP).

Pisałem wyżej. RPN = Reverse Polish Notation.

Cytat(1010 @ 4.10.2006, 20:35:19 ) *
Problem w tym że ja czytałem troche na ten temat i nie za bardzo rozumiem o co w tym wszystkim chodzi, tzn. jak z tego korzystać. Może udzielisz mi takiej pomocy...


Cytat(1010 @ 4.10.2006, 19:18:10 ) *
Powiedzmy że chce przy tym algorytmie pominąć RPN... Pozdro


Zdecyduj się. Chcesz czy nie chcesz korzystać z RPN.
Poza tym po co wymyślać coś na nowo MATH_RPN
1010
Okej wszystko spoko... Tylko ja musiałbym pzedstawić to wszystko etapowo... Czy idzie zapis ONP po wykonaniu jednego malego dzialania spowrotem zamienic na zwykly ? zeby to tak fajnie rozpisac?
cicik
Cytat(1010 @ 4.10.2006, 20:53:50 ) *
Okej wszystko spoko... Tylko ja musiałbym pzedstawić to wszystko etapowo... Czy idzie zapis ONP po wykonaniu jednego malego dzialania spowrotem zamienic na zwykly ? zeby to tak fajnie rozpisac?


Wszystko "idzie" tylko trzeba pomyśleć.

EDIT:
Bo mnie moderatorzy przestaną lubić.
Pobierasz ze stosu operator i jego argumenty, zastępujesz je wynikiem i konwertujesz z powrotem na zapois tradycyjny. I tak po każdym kroku. Algorytm konwersji ONP -> tradycyjny też można znaleźć.

@UDAT: Nie czytałem wszystkich odpowiedzi a jedynie przeszukałęm je na obecność terminu "odwrotna" lub "ONP" angielskiej nazwy nigdy nie używałem więc trochę powtórzyłem to co już było napisane.
1010
Myślałem nad tym ale niestety nie doszłem do tego jak takie coś rozwiązać...


Edit: Właśnie wczoraj szukałem algorytmu jakiegoś ONP - > tradycyjny i nic nie znalazłem...

Jeszcze poszukam...

Nom chyba że ktoś wie gdzie coś takiego znaleźć to chętnie przyjmę pomoc
cicik
Cytat(1010 @ 4.10.2006, 21:00:22 ) *
Jeszcze poszukam...

Nom chyba że ktoś wie gdzie coś takiego znaleźć to chętnie przyjmę pomoc


Wystarczy odwrócić algorytm konwersji tradycyjny -> ONP.
Pobierasz ze stosu operator i argumenty. Potem wsadzasz operator miedzy argumenty i wypluwasz ewentualnie dodając nawiasy w jeżeli operator ma niższy priorytet od następnego ze stosu.
Troche zabawy jest ale jak się chce to samemu można wymyśleć.
1010
Tylko że ONP likwiduje wszystkie nawiasy i wszystko... To przy odwrotnej konwersji nie ma później problemu z ich odzyskaniem?
cicik
Cytat(1010 @ 4.10.2006, 21:06:29 ) *
Tylko że ONP likwiduje wszystkie nawiasy i wszystko... To przy odwrotnej konwersji nie ma później problemu z ich odzyskaniem?


Jak pomyślisz to nie ma.
Pobierasz operator ze stosu i sprawdzasz czy następny operator na stosie ma wyższy czy niższy priorytet.
Jak wyższy to poprzednie działąnie bierzesz w nawias.

np:

4 2 3 + *

1. dajesz 4 na stos
2. dajesz 2 na stos
3. dajesz 3 na stos
4. dostajesz operator +
5. pobierasz 2 i 3 ze stosu i miedzy nie wsadzasz +. Dostajesz "2 + 3"
6. Pobierasz następny operator ze stosu. Jest nim *, który ma wyższy priorytet od + a więc "2 + 3" musisz wziąć w nawias. Otrzymujesz "(2 + 3)" i wsadzas tego stringa na stos zamiast "2 3 +"
7. Na stosie teraz masz 4 (2 + 3)
8. Pobierasz operator * i bierzesz ze stosu dwa jego argumenty czyli 4 oraz (2 + 3) i wsadzasz między nie operator.
9. Otrzymujesz 4 * (2 + 3). Na wejsciu nie ma już nic więc nie pakujesz tego w nawiasy.

Mogą wystąpić inne "sytuacje", które teraz mi do głowy nie przyszły ale generalnie wszystko da się zrobić.
1010
Jutro w takim razie popracuje nad konwerterami między tymi dwoma formatami...

Mam nadzieje że coś wyczaruje...
cicik
Teraz mi przyszłą do głowy jeszcze jedna rzecz, która chyba uprości sprawę totalnie.
Jest funkcja eval();

$dzialanie = '6 * (4 + 8)';
eval('$wynik = ' . $dzialanie);

Metoda powiedziałbym bruteforce'owa ale w php zadziała.

EDIT:
Sposób działa ale wyników pośrednich nie zwróci.
1010
To w takim razie odpada bo mi najbardziej właśnie zależy na wynikach pośrednich... Pozdro
Turgon
a nie prościej po prostu tak ...
rozbijasz explode i piszesz skrypt analizujący liczby.
1010
Jak by to było takie proste jak ci się wydaje to już dawno miałbym to gotowe...

Pozdro
Gnomik
Sam zastanawiałem się nad ONP i dalej nie jestem przekonany nad jego zastosowaniem tutaj. Zapis postfixowy nic tutaj tak własciwie nie zmienia, bo problem dalej pozostaje ten sam a zmienia się tylko jego zapis. Chodzi o etapowe rozwiązywanie i na bieżąco wyświetlanie postępu. Zaryzykowałbym nawet stwierdzenie że ONP tylko komplikuje sprawę, opuszczając nawiasy. To że taki zapis jest przystępniejszy maszynie nie znaczy że bliższy jest rozwiązaniu problemu.

Wg. mnie - chybiona droga, i zbędne bawienie się w konwersję ONP -> tradycyjne. Jasne, można tłumaczyć że wszystko w końcu sprowadza się do tej notacji, ale to że wszystko sprowadza się w końcu do zer i jedynek wcale nie znaczy że mamy się nimi bawić... winksmiley.jpg

Edit:
Cytat
to że wszystko sprowadza się w końcu do zer i jedynek wcale nie znaczy że mamy się nimi bawić... winksmiley.jpg
Wybacz 1010, nie mam nic złego na myśli biggrin.gif
cicik
Cytat(Gnomik @ 5.10.2006, 11:43:22 ) *
Sam zastanawiałem się nad ONP i dalej nie jestem przekonany nad jego zastosowaniem tutaj.


Ja się totalnie nie zgadzam z Twoją argumentacją. Według mnie ONP jest wręcz idealne do rozwiązania tego problemu. I powiem więcej... Po to zostało wymyślone.
Aztech
Jak najbardziej ONP nie komlikuje rozwiązania, ponieważ twoje operacje zdejmoane są ze stosu, więc wynik ostatniej operacji zawsze masz! natomiast dalzsze czytanei ze stosu i otaczanie tekstu nawiasami w zależności od poprzedniej operacji (a w zasadzie jej proprytetu) nie powinno stanowić problemu.
ONP ma właśnie ułtwiać takei programowanie
1010
Ok... Myslę że decyzja jest podjętna na korzyść ONP.

Teraz zaczynam bawic się nad algorytmami konwertowania:
Zapis tradycyjny -> ONP i
ONP -> Zapis tradycyjny

Jeżeli ma ktoś linki do jakiś przykładowych algorytmów to oczywiście pomoc chętnie przyjmę.

Dziś zacząłem bawić się nad funkcją:
zapis normalny -> ONP

Jednak nigdzie nie umiem znaleźć informacji na temat jak to można zrobić w odwrotną strone?

Czy ktoś wie gdzie takie coś mogę znaleźć...

Pozdro
cicik
Cytat(1010 @ 6.10.2006, 08:21:06 ) *
Jednak nigdzie nie umiem znaleźć informacji na temat jak to można zrobić w odwrotną strone?
Czy ktoś wie gdzie takie coś mogę znaleźć...


Programista dlatego jest programistą, że potrafi coś wymyśleć.
Inaczej programy pisaliby Chińczycy. Bez obrazy dla Chińczyków.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.