Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Vierekkäisten kirjainten vaihto [Java]

Sivun loppuun

Tommittaja [02.04.2009 18:33:58]

#

Nyt tuli kyllä ylivoimainen ongelma: pitäis saada toi tekstin tulostus loppumaan heti, kun se on tulostanut koko taulukon, mutta se tulostaa tekstin jotenkin oudosti sen jälkeen... en osaa siis lopettaa sen tulostusta kesken..

import java.util.Scanner;

public class Sekoituskone {
	public static Scanner Lue = new Scanner(System.in);
	public static void main(String[] args) {
		String teksti = Lue.nextLine();
		char[] taulu = teksti.toCharArray();
		for (int j = 0; j < taulu.length; ++j) {
			for (int i = j+1; i < taulu.length; ++i) {
				if (i % 2 == 0) {
					char apu = taulu[i];
					taulu[i] = taulu[j];
					taulu[j] = apu;
				} System.out.print(taulu[i]);
			} System.out.print(taulu[j]);
		}
	}
}

hunajavohveli [02.04.2009 18:45:28]

#

Mitä tuon nyt siis on tarkoitus tulostaa? Mikä osa on olennaista ja mikä pitäisi jättää tulostamatta?

Tommittaja [02.04.2009 18:48:41]

#

Esim: jos syöte on "perunakattila" tuloste on joka toinen alkio vaihdettuna edellisen kanssa, eli "epuranakttlia" tajusit varmaankin?

Edit: vika tulee siitä, että teen sen kahdella silmukalla, mutta en halua käyttää vain yhtä... ;P

Edit: ja nyt se tulosti: "epura­naktt­li­ae­u­pa­rantkl­tiu­ea­partnlk­tu­ae­aptrln­kau­aetplr­naa­u­telp­raa­tu­le­pa­ta­lu­e­ta­laut­laal­taltl"

hunajavohveli [02.04.2009 19:22:37]

#

Jos taulukon pitää joka tapauksessa jäädä sekoitetuksi, tuo kannattanee hoitaa kahdessa osassa: Ensin sekoitat taulukon sisällön ja vasta sitten tulostat sen, sen sijaan, että yrittäisit tehdä molemmat sekaisin. Tulostaminen onnistuu tietenkin tavallisella silmukalla. Sekoittamisenkin voi hoitaa yhdellä silmukalla esim. näin:

int pituus = (taulu.length % 2 == 0) ? taulu.length : taulu.length - 1;
for(int i = 0; i < pituus; i += 2) {
	char apu = taulu[i];
	taulu[i] = taulu[i + 1];
	taulu[i + 1] = apu;
}

Tässä siis i käy läpi joka toisen indeksin ja joka kierroksella taulu[i] vaihdetaan taulu[i + 1]:n kanssa. Ensimmäisellä rivillä varmistetaan, että viimeinen merkki jätetään käymättä läpi, jos pituus ei ole parillinen.

eq [02.04.2009 19:23:21]

#

Tommittaja kirjoitti:

Esim: jos syöte on "perunakattila" tuloste on joka toinen alkio vaihdettuna edellisen kanssa, eli "epuranakttlia" tajusit varmaankin?

Edit: vika tulee siitä, että teen sen kahdella silmukalla, mutta en halua käyttää vain yhtä... ;P

Sisennysten selkeyden nimissä älä tee tulostusta noin. Yksinkertaisesti, älä.

Tiedätköhän nyt muutenkaan mitä tarkalleen ottaen olet tekemässä? Vierekkäisten kirjainten vaihtoon ei ole mitenkään mielekästä käyttää kahta silmukkaa, eikä esimerkiksi koodisi muokkaa taulun sisältöä kuvaamallasi tavalla; en jaksa pähkäillä tulostetta, mutta taulun sisältö muuttuu jotakuinkin seuraavalla tavalla:

ABCDE -> CBADE
CBADE -> EBADC
EBADC -> EABDC
EABDC -> ECBDA
ECBDA -> ECADB
ECADB -> ECABD (loppu)

Ei aivan mitä voisi odottaa, jos kerta tulostuste näyttää pitkälti oikealta sekaan tungettujen tulostusfunktioiden myötä (joita siis kutsutaan yhteensä aivan liikaa, jos halutaan vain taulu.length määrä kirjaimia)

Suositukseni: pyri tekemään haluamasi muunnos taulun sisällölle, ja tulosta tämä sitten kerralla. Datan toimittaminen standardi-ulostulosta muille funktioille kun voi olla kertaluokkaa vaativampaa.

edit:
hunajavohveli antoi hyvän ratkaisun, mutta vastaavan pohtiminen itse on silti suotavaa (olettaen, ettet ole ratkaisua aiemmin keksinyt). Suosittelen (vastaavassa "algoritmissa") kuitenkin aloittamaan i:n arvolla yksi, ja swappaamaan siis indeksit i ja i-1; tällöinkään et voi mennä taulukon yli (kuten et Javassa muutenkaan), eikä taulukon pituuden parillisuuttakaan tarvitse tarkistaa.

Tommittaja [02.04.2009 19:34:36]

#

hmm... taidan kuitenkin ENSIN tehdä sen näin: teen uuden muuttujan, jonka alkuarvo on 0. Sitten suurennan sitä joka silmukan kierroksella, sitten vertaan, onko muuttuja taulu.length, jos on, niin breakataan ulos ;D

Edit: mitä tuo '?' operaattori edes tekee?

Edit: NYT TOIMII! sori tuosta sisennyksestä vielä, mutta voin kyllä sen joskus korjata. Tässä itse koodi:

import java.util.Scanner;

public class Sekoituskone {
	public static Scanner Lue = new Scanner(System.in);
	public static void main(String[] args) {
		String teksti = Lue.nextLine();
		int breakkaaja = 0;
		char[] taulu = teksti.toCharArray();
		for (int j = 0; j < taulu.length; ++j) {
			for (int i = j+1; i < taulu.length; ++i) {
				if (i % 2 == 0) {
					char apu = taulu[i];
					taulu[i] = taulu[j];
					taulu[j] = apu;
				} System.out.print(taulu[i]);
				breakkaaja += 1;
				if (breakkaaja == taulu.length)
					break;
			} System.out.print(taulu[j]);
			breakkaaja += 1;
			if (breakkaaja == taulu.length)
				break;
		}
	}
}

Tommittaja [04.04.2009 16:05:48]

#

ok, näköjään Scannerilla voi lukea aika suuren pätkän tekstiä yhteen muuttujaan; testasin 3800 merkkiä pitkällä jonolla ;D

Metabolix [04.04.2009 20:47:15]

#

Äly hoi. Kannattaa ihan oikeasti joskus opetella ottamaan opikseen neuvoista. Koodissasi ei ole mitään järkeä, teet hirveästi turhaa työtä ja tuotat lisäksi merkkitaulukon, jossa merkit eivät ole sen paremmin alkuperäisessä kuin tulostettavassakaan järjestyksessä.

12345678 # syöte
21436587 # tuloste
72143658 # taulukko

Kun siis tarkoituksesi on ilmeisesti vain tulostaa teksti hassusti, on tyhmää kikkailla taulukolla aivan käsittämättömiä.

// Tulostetaan kaksi merkkiä kerrallaan eri järjestyksessä.
for (int i = 0; i < teksti.length() - 1; i += 2) {
  System.out.print(teksti.charAt(i + 1));
  System.out.print(teksti.charAt(i));
}
// Lopuksi tulostetaan parittoman tekstin viimeinen merkki ja rivinvaihto.
System.out.println(teksti.substring(teksti.length() / 2 * 2));

Tämä ja hunajavohvelin ehdotus ovat ongelman järkevät ratkaisumallit.

Omassa koodissasi ei ole tolkkua. Siitä voi nopeasti todeta, että breakkaaja-muuttujan arvo sisemmän silmukan lopussa on taulu.length-1, sitten sitä nostetaan kerran, ulommasta silmukasta päästään heti ensimmäisellä kierroksella ulos. Tämän perusteella koodiasi voidaan tiivistää seuraavasti:

final int j = 0;
        //for (int j = 0; j < taulu.length; ++j) {
            for (int i = j+1; i < taulu.length; ++i) {
                if (i % 2 == 0) {
                    char apu = taulu[i];
                    taulu[i] = taulu[j];
                    taulu[j] = apu;
                } System.out.print(taulu[i]);
                //breakkaaja += 1;
                //if (breakkaaja == taulu.length)
                    //break;
            } System.out.print(taulu[j]);
            //breakkaaja += 1;
            //if (breakkaaja == taulu.length)
                //break;
        //}

Eli ilman kommenttirivejä ja j:tä:

for (int i = 1; i < taulu.length; ++i) {
    if (i % 2 == 0) {
        char apu = taulu[i];
        taulu[i] = taulu[0];
        taulu[0] = apu;
    }
    System.out.print(taulu[i]);
}
System.out.print(taulu[0]);

Tässäkään taulukon alkioiden heittelyssä ei ole erityisemmin järkeä, koska koodin todellinen toimintaperiaate on olennaisesti tämä:

int i;
for (i = 1; i < taulu.length; ++i) {
    if (i % 2 == 0) {
        System.out.print(taulu[i-2]);
    } else {
        System.out.print(taulu[i]);
    }
}
if (taulu.length % 2 == 0) {
    System.out.print(taulu[i - 2]);
} else {
    System.out.print(taulu[i - 1]);
}

Jos koodi näyttää turhan pitkältä, sen voi tietenkin tiivistää hieman kryptisemmäksi:

for (int i = 1; i < taulu.length; ++i) {
    System.out.print(taulu[i - 2 + 2 * (i % 2)]);
}
System.out.print(taulu[taulu.length - 2 + taulu.length % 2]);

Tämä koodi (ja siten sinun merkillinen versiosi) on periaatteeltaan minun ratkaisuni variantti, mutta aivan turhaa koodia on kerta kaikkiaan liikaa.

Selvästikin sinulla on siis vielä paljon varaa parantaa sekä ymmärrystäsi siitä, mitä kirjoittamasi koodi tekee, että kykyäsi suunnitella, miten saisit koodin tekemään, mitä haluat.

Tommittaja [04.04.2009 21:30:29]

#

Onpas mukavaa kun ollaan noin mukavia ja positiivisia

en edes ymmärtänyt tuota hunajavohvelin esimerkkiä, kun siinä on operaattoreita, joita en edes osaa. Hyvä tuossa ottaa mallia, kun ei tiedä mitä koodi edes tekee.. Ja tuo koodinihan toimii, vai?

Edit: miten niin tuo taulukko on noin, miten se muka tulostaa oikein, jos se taulukko on väärin?

Edit2: en kyllä ihan usko, että itsekään olit täydellinen muutaman kuukauden ohjelmoinnin jälkeen, ja ei ole pakko vastata, jos ei ole muuta kuin valitusta

Teuro [04.04.2009 22:39:34]

#

Alla olevaan lainaukseen on pakko hiukan kommentoida.

Tommittaja kirjoitti:

Onpas mukavaa kun ollaan noin mukavia ja positiivisia

en edes ymmärtänyt tuota hunajavohvelin esimerkkiä, kun siinä on operaattoreita, joita en edes osaa. Hyvä tuossa ottaa mallia, kun ei tiedä mitä koodi edes tekee.. Ja tuo koodinihan toimii, vai?

Et siis ymmärrä tuota ? -operaattoria? Minusta tuo on jopa verraten helppo, vaikka en tuota olisikaan ennen nähnyt. Selvästikin ensin kokeillaan josko stringin pituus olisi jaollinen kahdella, mutta jos se ei ole, niin pituus on stringin pituus-1. Tämänkin asian olisit luultavasti selvittänyt javan dokumentaatiosta.

Muutenkin asenteesi on minusta kummallinen, koska ensin pyydät apua (ohjelmointi)ongelmiisi. Sitten kun sinulle vastataan jopa esimerkin tai valmiin koodin kanssa, niin suhtaudut varsin epämiellyttävällä tavalla vastaajiin.

Metabolixin kommentissa olevat piikit on helpohko ymmärtää, koska kyselet edelleen minusta asioita, jotka olisi pääteltävissä helposti itsekin.

Metabolix [04.04.2009 23:20:32]

#

Tommittaja kirjoitti:

Edit: miten niin tuo taulukko on noin, miten se muka tulostaa oikein, jos se taulukko on väärin?

Luitko viestiäni — tai edes omaa koodiasi? Avasin koodirivejäsi mielestäni varsin selkeästi, ja versiosta "ilman kommenttirivejä ja j:tä" näet, että tulostat mm. taulukon alkuun päätyneen merkin vasta lopuksi. Et missään vaiheessa tulosta koko taulukkoa yhtenäisesti, joten tietenkään lopputuloskaan ei vastaa taulukon sisältöä.

Taulukon sisällön voit itse todeta lisäämällä koodisi loppuun seuraavan rivin:

System.out.println(new String(taulu));

Koodin toimivuus ei ole ainoa tai aina edes suurin arvo, joskus toivottavasti opit sen. Kenellekään ei ole hyötyä tuon koodin toimimisesta, joten sen kohdalla toimiminen on sivuseikka; sen sijaan sinulle olisi hyötyä, jos tekisit tuon järkevästi ja siinä sivussa oppisit ajattelemaan paremmin, koska sitä ajattelutaitoa tarvitset elämässäsi huomattavasti enemmän kuin Java-ohjelmaa, joka vaihtaa peräkkäisten kirjainten paikkoja.

Selvennänpä vielä, mitkä ne kaksi järkevää ratkaisumallia ovat: joko teksti muokataan sopivaksi (kuten hunajavohveli teki) tai se tulostetaan palasina muuttamatta alkuperäistä tekstiä (oma versioni).

Päärynämies [05.04.2009 16:47:47]

#

Ei tosiaan nyt kannata Tommittajan itseensä ottaa. Minusta sinä täältä saat arvokkaita neuvoja, että miten parantaa koodiasi ja osaamistasi, toivottavasti tajuat myös vain lukea ne ajatuksen kanssa. Täällä on kumminkin neuvomassa ihmisiä, jotka ovat näitä juttuja ties kuinka paljon jo puuhanneet, opiskelleet tai työkseen tehneet, osaavaa väkeä löytyy.

Ehkä Metabolixin viesti ei ollut se kaikkein hienovaraisin. Minusta hän kuitenkin perusteli näkökantansa hyvin ja esitti parannusehdotukset, eikä vain valittanut koodistasi. Ehkä hän enemmänkin kritisoi.

Ei kukaan odotakaan sinun täydellinen olevan, tuskin kukaan täällä on, jokaisella on jotain opittavaa. Ja jos tänne joku samantasoita koodia esittää kuin oli ratkaisussasi, niin varmasti joku sen toteutusta kommentoi ja kritisoi.


Sivun alkuun

Vastaus

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

Tietoa sivustosta