Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Java: Anagrammi

Sivun loppuun

JRokka [09.11.2019 22:18:19]

#

Tässä ohjelma tarkistaa, ovatko sanat anagrammeja. Sana ovat anagrammeja, jos niissä on samat merkit. Oletetaan aluksi että sanat ovat anagrammeja.

Koodi

import java.util.Scanner;

public class Anagrammi {
    public static void main(String[] args){
        Scanner syote = new Scanner(System.in);
        String mjono = "";
        String mjono_2 = "";
        boolean onkoAnagrammi = true; //Oletetaan, että sanat ovat anagrammeja.
        //Syötetään lähtötiedot.
        System.out.println("Syötä kaksi merkkijonoa.");
        mjono = syote.next();
        mjono_2 = syote.next();
        //Jotta voidaan ylipäänsä olettaa, että sanat ovat anagrammeja tulee niiden olla yhtä pitkiä.
        if (mjono.length() == mjono_2.length()){
            //Järjestetään merkkijonot, jotta niitä olisi helpompi käsitellä.
            char[] merkit = mjono.toCharArray();
            char[] merkit_2 = mjono_2.toCharArray();
            char temp = ' ';
            for (int x = 0; x < merkit.length-1; x++){
                for (int y = x+1; y < merkit.length; y++){
                    if (merkit[x] > merkit[y]){
                        temp = merkit[x];
                        merkit[x] = merkit[y];
                        merkit[y] = temp;
                    }
                }
            }
            for (int x = 0; x < merkit_2.length-1; x++){
                for (int y = x+1; y < merkit_2.length; y++){
                    if (merkit_2[x] > merkit_2[y]){
                        temp = merkit_2[x];
                        merkit_2[x] = merkit_2[y];
                        merkit_2[y] = temp;
                    }
                }
            }
            //Katsotaan, ovatko sanat anagrammeja.
            //Jos yksikin merkki eroaa, kyseessä ei ole anagrammi.
            //Käydään kaikki merkit läpi.
            for (int x = 0; x < merkit.length; x++){
                if (merkit[x] != merkit_2[x]){
                    onkoAnagrammi = false;
                }
            }
            //Näytetään tulos.
            if (onkoAnagrammi == true){
                System.out.println("Anagrammi");
            }
            else {
                System.out.println("Ei ole anagrammi");
            }
        }
    }

}

jalski [10.11.2019 09:36:53]

#

Tuosta saa paljon nopeamman:

Naiivi versio toimisi siten, että lajiteltaisiin sanan kirjaimet aakkosjärjestykseen ja käytettäisiin tätä avaimena map tietorakenteeseen. Jos avainta ei ole, luo lista, työnnä sana kyseiseen listaan ja lisää avaimella mappiin. Jos avain löytyy niin lisää sana avaimen takana olevaa listaan.

Nopeampi versio toimii sanan kirjainten lajittelun sijaan laskemalla sanalle arvo prime hash funktiolla ja käyttämällä tätä avaimena.

Alla toteutus 8th ohjelmointikielellä:

\ Find anagrams in a word list:

m:new constant anamap

\ Primes array. Start of array is padded with zeros to elimate calculation.
[
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
  73, 79, 83, 89, 97, 101 ] constant primes

: prime-hash  \ s -- s
  1 swap
  ( primes swap a:@ nip n:* )
  s:each! "%x" s:strfmt ;

: process-words \ word --
  /^[a-z]{3,}$/ r:match if
    r:str nip dup >r prime-hash
    anamap over m:@ null? if
      drop swap a:new r> a:push m:!
    else
      r> a:push 2drop
    then
  then drop ;

\ load and process the file requested:
: read-and-check-words  \ fname --
  f:slurp "Cannot open and read file, nothing to process" thrownull
  ' process-words s:eachline ;

\ for sorting the word keys array:
: key-val-cmp         \ key1 key2 -- cmp
  anamap swap m:@     \ key1 anamap key2val
  swap rot m:@        \ val2 anamap val1
  0 a:@ nip           \ val2 anamap v1
  rot 0 a:@ nip       \ map v1 v2
  s:cmp nip ;

: sort-keys-by-first-word \ keys1 -- keys2
  ' key-val-cmp a:sort ;

: app:main
  0 args "/usr/share/dict/british-english-insane" ?:
  read-and-check-words

  \ get an array of those keys which have at least 2 elements:
  a:new anamap ( a:len nip 1 n:> if a:push else drop then ) m:each swap

  \ print the anagram list in order of first-word:
  sort-keys-by-first-word
  m:@@ nip ( 0 a:@ ": " s:+ swap 0 a:- ", " a:join s:+ "\n" s:+ . ) a:each! drop
  bye ;

Tronic [10.11.2019 10:21:46]

#

Python-koodi tulostaa kaikki sanakirjasta löytyneet anagrammijoukot.

from collections import defaultdict

d = defaultdict(set)
with open("/usr/share/dict/words") as f:
    for word in f.read().split():
        key = "".join(sorted(word.upper()))
        d[key].add(word)
print([
    val
    for key, val in d.items()
    if len(key) >= 3 and len(val) > 1
])

jalski [10.11.2019 10:47:47]

#

Tronic kirjoitti:

Python-koodi tulostaa kaikki sanakirjasta löytyneet anagrammijoukot.

Python koodi on kyllä lyhyt, mutta oletko kokeillut mikä on suorituskyky esim. käyttämällä british-english-insane sanakirjaa? Oma veikkaukseni on, että ei suoriudu kauhean nopeasti...

Oma 8th toteutukseni suoriutuu tehtävästä Windows alustalla 13.5 sekunnissa ja muilla alustoilla joitain sekunteja vielä tuota nopeammin.

EDIT: On riittävän nopea kyllä, mutta ei tee samaa kuin oma 8th koodini...

The Alchemist [10.11.2019 12:39:14]

#

Hänen python-koodillaan on sentään jotain arvoa toisin kuin sellaisella räpellyksellä, joka on kirjoitettu täysin turhalla 8th:llä...

Mango [10.11.2019 13:09:16]

#

Eipä ole koskaan tullut vastaan yhtään reaalimaailman käyttötapausta jossa olisi ollut tarpeen testata/etsiä anagrammeja, joten kielestä riippumatta minkä tahansa toteutuksen arvo lähenee nollaa.

jalski [10.11.2019 14:06:28]

#

The Alchemist kirjoitti:

Hänen python-koodillaan on sentään jotain arvoa toisin kuin sellaisella räpellyksellä, joka on kirjoitettu täysin turhalla 8th:llä...

Perustelu? Mikä tekee koodistani räpellyksen? Mikä tekee 8th:sta turhan tai Pythonia huonomman työkalun? Koodi on toimiva, kommentoitu ja toimintaperiaate ei ole sidottu ohjelmointikieleen.

Foorumeille kirjoiteltaessa olisi muuten suotavaa omata edes minimaaliset käytöstavat. Epäystävällinen tapasi keskustella tällä foorumilla ei palvele ketään ja kukaan ohjelmoinnista kiinnostunut aloittelija ei varmasti siitä rohkaistu. Harmittaa näiden henkilöiden puolesta itseään täynnä olevan kaverin suunsoitto, jonka oma osaaminen ei valitettavasti ole sillä tasolla mitä omat luulot ovat...

Tronic [11.11.2019 07:55:16]

#

Ihan mielenkiinnosta: mikä saa käyttämään kaupallista Forth-johdannaista kieltä? Mistä kuulit ko. kielestä ja miten innostuit siitä? Onko aiempaa taustaa Forthista tai muista RPN-stack-koneista?

jalski [11.11.2019 17:34:02]

#

Tronic kirjoitti:

Ihan mielenkiinnosta: mikä saa käyttämään kaupallista Forth-johdannaista kieltä? Mistä kuulit ko. kielestä ja miten innostuit siitä? Onko aiempaa taustaa Forthista tai muista RPN-stack-koneista?

Törmäsin 8th ohjelmointikieleen puoli vahingossa ja tykästyin siihen. En pidä ohjelmointikielen kaupallisuutta huonona tai ratkaisevana asiana. Ainakin tiedän, että jos tulee ongelma tai löydän bugin, niin se yleensä korjataan melkein välittömästi. Itse käytän professional versiota ja tuon hinta oli vähemmän kuin mitä keskimääräinen baarireissuni maksaisi. Forth ohjelmointikieleen taas tutustuin Jupiter Ace tietokoneen kautta. Toki ahkerassa käytössäni on myös PL/I ja Fortran kääntäjät.

The Alchemist [12.11.2019 03:32:13]

#

jalski kirjoitti:

Foorumeille kirjoiteltaessa olisi muuten suotavaa omata edes minimaaliset käytöstavat. Epäystävällinen tapasi keskustella tällä foorumilla ei palvele ketään ja kukaan ohjelmoinnista kiinnostunut aloittelija ei varmasti siitä rohkaistu. Harmittaa näiden henkilöiden puolesta itseään täynnä olevan kaverin suunsoitto, jonka oma osaaminen ei valitettavasti ole sillä tasolla mitä omat luulot ovat...

Älä postaa roskaa, josset kestä kritiikkiä... Ei tuo 8th:llä egoilu ole keneltäkään kirvoittanut positiviisia reaktioita tähän mennessä. Vähän kuin kehuskelisi olevansa runoilija, muttei koskaan kirjoita muualle kuin vahaliidulla vessan seinään.

jalski [12.11.2019 06:40:55]

#

The Alchemist kirjoitti:

Älä postaa roskaa, josset kestä kritiikkiä... Ei tuo 8th:llä egoilu ole keneltäkään kirvoittanut positiviisia reaktioita tähän mennessä.

Mitä ihmeen roskaa tai egoilua? Olen postaamissani vastauksissa kertonut, mitä niissä tehdään, miksi tehdään ja ne on kommentoitu. Vastaukseni ja ratkaisumallini eivät varsinaisesti mitenkään ole olleet sidottu ohjelmointikieleen.

Omien viestiesi sävy taas on aina negatiivinen ja riitaa hakeva. En nyt suoraan sanottuna jaksa enempää keskustella henkiseltä kehitykseltään viisi vuotiaan tasolla olevan kaverin kanssa! Turha pään aukominen jokaiseen viestiketjuun foorumilla ei muuten ole kritiikkiä.

Tronic [12.11.2019 08:10:00]

#

Vastauksesi ovat nimenomaan sidottuja ohjelmointikieleen, sillä 8th syntaksi on niin hankalaa, ettei kokenutkaan ohjelmoija saa siitä juurikaan selvää edes kommenttien kanssa, vaikka algoritmikin on tuttu. Vrt. esim. C#-toteutukseen, jonka groupby javascriptistä tutulla lambda-syntaksilla oli toiminnaltaan melkoisen selkeä, vaikkei edes sitä lambdaa olisi ymmärtänyt.

The Alchemist [13.11.2019 11:24:12]

#

Juuri sen takia, jalski, sinä postailet 8th:llä koodattuja esimerkkejä, että sen syntaksi on yleisesti ottaen hyvin outo ja kryptinen. Jos sinua kiinnostaisi vähääkään sivistää muita lukijoita algoritmitietoudella eikä vain egoilla marginaalinen kielen tuntemuksesta, niin käyttäisit jotain yleisempää kieltä.

Eri mieltä saa olla mutta valehdella ei tarvitse.

jalski [13.11.2019 12:50:09]

#

The Alchemist kirjoitti:

(13.11.2019 11:24:12): Juuri sen takia, jalski, sinä postailet 8th:llä...

Onko vaikea ymmärtää, että käytän 8th:ta lähestulkoon kaikkeen ohjelmointiin nykyään? Tämän ketjun esimerkissä oli sanallinen selostus toimintamallista ennen koodia ja lisäksi koodi oli kohtuullisesti kommentoitu. Mielestäni esimerkiksi Python toteutus ei ole yhtään helppolukuisempi.

Osaan myös PL/1 ja Fortran ohjelmointikieliä kohtuullisesti, mutta näiden käytöstäkin varmasti olisit löytänyt jotain urputettavaa! Oletko muuten ikinä kirjoittanut kokonaista ohjelmaa millään ohjelmointikielellä? Meinaan vaan, että ehkä sinun pitäisi pitäytyä vaan nettisivujen vääntämisessä ja jättää oikea koodaaminen aikuisille...

Mango [13.11.2019 19:16:02]

#

The Alchemist kirjoitti:

Juuri sen takia, jalski, sinä postailet 8th:llä koodattuja esimerkkejä, että sen syntaksi on yleisesti ottaen hyvin outo ja kryptinen.

Mitä väliä sillä on kuinka outo tai kryptinen joku kieli on? Voisi kuvitella että harrastajafoorumilla oltaisiin avomielisiä kaikkea erilaista kohtaan? Itse ainakin näen mielelläni tavanomaisuudesta poikkeavia ratkaisuja vaikka ei niitä koskaan missään oikeassa työssä hyödyntäisikään. Ja jos jokin aihe ei kiinnosta niin ohitan sen kohteliaasti enkä vedä asiasta hernettä nenään.

lainaus:

Jos sinua kiinnostaisi vähääkään sivistää muita lukijoita algoritmitietoudella eikä vain egoilla marginaalinen kielen tuntemuksesta

Tälläisestä tekstistä haisee lähinnä kommentoijan oman egon heikkous. Pidä sinä se sivistäjän viitta harteillasi jos asia on niin lähellä sydäntä ja anna muiden tehdä omat juttunsa. Live and let live you know.

Mutta joo, sinänsä ei ole yllättävää että foorumi on kuollut pystyyn kun täällä lähinnä muutamat besserwisserit puolustavat reviiriään ja äksyilevät pois kaiken normista poikkeavan. Ja saa kuollakin pois, ei ole minun aikani arvoista. Kiitos ja näkemiin, toivottavasti ei tavata oikeassa maailmassa.

Metabolix [13.11.2019 21:52:38]

#

Mielestäni tässä molemmat osapuolet ovat jossain määrin oikeassa.

Kritiikkiä voi esittää perustelujen kera ja ilman vihaisia tai loukkaavia sanavalintoja. Luultavasti myös vaste kritiikkiin on silloin parempi. Tahallinen väärinymmärrys ja ehdottomuus eivät myöskään vie keskustelua eteenpäin.

jalski:

Minustakin 8th-koodit ovat keskustelussa ongelmallisia.

Useimmissa kielissä käytetään tuttuja sanoja ja koulusta tuttua laskujärjestystä, ja funktiot ja arvot erottuvat toisistaan tutulla tavalla. Sen sijaan 8th-koodista ei ole automaattisesti selvää edes koodin perusrakenne. Mikä on arvo ja mikä on operaatio? Mitä tekevät kaikki nämä muutaman kirjaimen lyhenteet ja symbolit? Mitä ihmettä mahtaa tarkoittaa esimerkiksi ”r:str nip dup >r prime-hash”? (Ei tarvitse vastata.) Olen ohjelmoinut kymmenillä eri kielillä, mutta 8th-koodia en osaa oikeasti lukea.

Usein lähetät koodeja keskusteluihin, joissa päähenkilö eli kysymyksen esittäjä ei osaa edes itselleen tutuinta ohjelmointikieltä kovin hyvin. Mahdollisuudet vieraan ja tyyliltään täysin erilaisen kielen ymmärtämiseen ovat silloin aivan erityisen huonot.

Sanot, että koodi on kommentoitu, mutta katso nyt hetki itse niitä kommentteja, joissa on ylipäänsä ihmiskielistä tekstiä:

\ Find anagrams in a word list:
\ Primes array. Start of array is padded with zeros to elimate calculation.
\ load and process the file requested:
\ for sorting the word keys array:
\ get an array of those keys which have at least 2 elements:
\ print the anagram list in order of first-word:

Näistä kommenteista ja funktioiden nimistä ei ole vielä juurikaan apua koodin toiminnan ymmärtämisessä. Koodin varsinaista toimintaa ei pysty lukemaan, jos ei osaa 8th:ta tai jotain aivan lähisukuista kieltä – ja uskon, että juuri kukaan kävijöistä ei osaa.

Tilannetta voi melkeinpä verrata siihen, että pitäisi lukea hepreankielistä Koraania niin, että vain jokaisen suuran otsikko on suomennettu. Ei sitä varmasti kukaan lue, jos ei osaa hepreaa tai ole saanut jotain ihmeellistä herätystä.

Jos haluaa antaa esimerkkejä tuollaisella kielellä, olisi järkevää kommentoida jokainen tai lähes jokainen rivi niin, että lukija pystyisi oikeasti seuraamaan koodin toimintaa.

PL/I ja Fortran 95 ovat muodoltaan huomattavasti tutumpia kieliä, joten niistä lukija voi saada jotain selvää. Toisaalta koodiesimerkkejä annettaessa olisi viisasta miettiä asiaa siltä kannalta, mikä hyödyttää lukijaa: jos esimerkki käyttää ”näppärästi” PL/I:n bittijonokikkailua tai muuta vastaavaa erikoisuutta, esimerkin soveltaminen muihin kieliin tulee siltä istumalta tuhannesti vaikeammaksi. Keskustelun kannalta järkevää olisi siis esitellä hyvää koodia sillä kielellä, jota keskustelussa jo käytetään, tai esitellä muulla kielellä mahdollisimman helposti soveltuva ja ymmärrettävä ratkaisu.

Mitä vaikeampi koodi on (kielivalinnan tai muun syyn vuoksi), sitä selvemmin kannattaisi kuvata myös ratkaisun idea. Tokkopa tämän keskustelun aloittajaa auttaa ohje, että ”nopeampi versio toimii laskemalla sanalle arvo prime hash funktiolla”, vaan asiasta voisi kertoa ainakin kymmenen lauseen verran. Aloittajan Java-valinnan huomioiden kannattaisi kertoa myös teknisistä asioista kuten siitä, että ratkaisu edellyttää pitkien lukujen käyttöä.

tkok [20.11.2019 16:48:27]

#

JRokka kirjoitti:

for (int x = 0; x < merkit.length; x++){
    if (merkit[x] != merkit_2[x]){
        onkoAnagrammi = false;
    }
}

For-silmukan suorituksen voi keskeyttää, kun löytyy yksikin poikkeus. Tämän ohjelman kokonaisuudessa se ei tuota huomattavaa etua, mutta on hyvä opetella hallitsemaan koodinsa suoritus ja kontorlli mm. for-silmukoiden osalta break ja continue -käskyillä.

// esimerkki 1, break keskeyttää for-silmukan, kun löytyy yksikin poikkeava
for (int x = 0; x < merkit.length; x++){
    if (merkit[x] != merkit_2[x]){
        onkoAnagrammi = false;
        break;
    }
}
// esimerkki 2, onkoAnagrammi-muuttujan totuusarvoa voi hyödyntää suoraan for-
// silmukan vertailuosassa
for (int x = 0; x < merkit.length && onkoAnagrammi; x++){
    if (merkit[x] != merkit_2[x]){
        onkoAnagrammi = false;
    }
}

Esimerkki 2 on tässä kohtaa mielestäni huonompi, kun ei ole ilmiselvää for-loopin määrittelyä lukiessa, miksi onkoAnagrammi on mukana totuusvertailussa.

JRokka kirjoitti:

if (onkoAnagrammi == true){
// - -
}

En ole vähään aikaan nähnyt boolean vertailua totuusarvon kesken. Harmaan päivän piristys, kiitos.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta