Pieniä kysymyksiä ohjelmoinnista

Jos oikein ymmärsin, niin jotakin tämän kaltaistako ?
Koodi:
SELECT * FROM osat;
+----+-----------+
| id | osanimi   |
+----+-----------+
|  1 | Suristin  |
|  2 | Päristin  |
|  3 | Perse     |
|  4 | Kairain   |
+----+-----------+
SELECT * FROM tuotteet;
+----+------------------+
| id | tuotenimi        |
+----+------------------+
|  1 | Perseensuristin  |
|  2 | Perseenpäristin  |
+----+------------------+
SELECT * FROM osa_tuote;
+--------+----------+
| osa_id | tuote_id |
+--------+----------+
|      1 |        1 |
|      3 |        1 |
|      2 |        2 |
|      3 |        2 |
+--------+----------+
SELECT o.id,o.osanimi,MIN(t.tuotenimi) AS tuotenimi, COUNT(t.id) as tuotteita
FROM osat AS o
LEFT JOIN osa_tuote AS ot ON o.id=ot.osa_id
LEFT JOIN tuotteet AS t ON ot.tuote_id=t.id GROUP BY o.id;
+----+-----------+------------------+-----------+
| id | osanimi   | tuotenimi        | tuotteita |
+----+-----------+------------------+-----------+
|  1 | Suristin  | Perseensuristin  |         1 |
|  2 | Päristin  | Perseenpäristin  |         1 |
|  3 | Perse     | Perseenpäristin  |         2 |
|  4 | Kairain   | NULL             |         0 |
+----+-----------+------------------+-----------+
Tästä nähdään että kumpikaan tuote ei mahdu, koska kairain puuttuu molemmista :D
Ratkaisevana tekijänä jonkin aggrekaattifunktion käyttö (MIN(t.tuotenimi)) sellaisille columneille, joita ei groupata. Välttämättä tämä ei ole paras mahdollinen tapa taklata käsillä oleva ongelma, mutta toimii isohkoillakin datamäärillä kohtuu nopeasti.

Eli siis jos osalla on 10 tekstisaraketta niin jokaiseen MIN() ?

Selvennetään vielä että tarkoitus on siis hakea esim. osalistaus ja queryssä _saattaa_ olla lisäksi where lause kuten WHERE osanimi like '%suri%'
Ja miksikö tämmöstä, siksi että listaukseen saisi mahdollisimman tehokkaasti yhden osan vain yhden kerran ja jokaiselle osalle sarakkeeseen yhden tuotteen ja erityisesti kun kuvien liitos toimii samalla periaatteella niin yhden kuvan, ei niin väliä edes että mikä kuva, tai kai senkin jollain id:llä saisi varmaan järjestettyä
 
Eli siis jos osalla on 10 tekstisaraketta niin jokaiseen MIN() ?

Selvennetään vielä että tarkoitus on siis hakea esim. osalistaus ja queryssä _saattaa_ olla lisäksi where lause kuten WHERE osanimi like '%suri%'
Ja miksikö tämmöstä, siksi että listaukseen saisi mahdollisimman tehokkaasti yhden osan vain yhden kerran ja jokaiselle osalle sarakkeeseen yhden tuotteen ja erityisesti kun kuvien liitos toimii samalla periaatteella niin yhden kuvan, ei niin väliä edes että mikä kuva, tai kai senkin jollain id:llä saisi varmaan järjestettyä
Lisäämällä tuotteen muita sarakkeita MIN() tai MAX() funktioilla saat kyllä lopputuloksena osat vain yhteen kertaan, mutta lopputulos voi yllättää. Tuossa nimittäin käy niin, että tuotteen lisäkentät eivät välttämättä tule samasta tuotteesta, sillä MIN() ja MAX() palauttavat tekstikentistä aakkosjärjestyksessä ensimmäisen tai viimeisen tekstikentän niistä tuotteista jotka kyseiseen osaan on liitetty.

Tässä alikyselyllä toteutettu versio, jolla saat vaikka tuotteen kaikki sarakkeet mukaan tulokseen:
Koodi:
SELECT z.*,y.tuotenimi
FROM (
    SELECT o.id,o.osanimi,MIN(t.id) AS tuoteid, COUNT(t.id) as tuotteita
    FROM osat AS o
    LEFT JOIN osa_tuote AS ot ON o.id=ot.osa_id
    LEFT JOIN tuotteet AS t ON ot.tuote_id=t.id
    GROUP BY o.id
) AS z
LEFT JOIN tuotteet AS y ON y.id=z.tuoteid;

Ja jos osia halutaan rajata, niin WHERE tuonne alikyselyyn:
SELECT z.*,y.tuotenimi
FROM (
    SELECT o.id,o.osanimi,MIN(t.id) AS tuoteid, COUNT(t.id) as tuotteita
    FROM osat AS o
    LEFT JOIN osa_tuote AS ot ON o.id=ot.osa_id
    LEFT JOIN tuotteet AS t ON ot.tuote_id=t.id
    WHERE o.osanimi LIKE '%sur%'
    GROUP BY o.id
) AS z
LEFT JOIN tuotteet AS y ON y.id=z.tuoteid;
 
Jos docker kontilla on kansio data jossa on tiedostoja ja host voluumi data on taas tyhjä niin meneekö kontin tiedostot sitten tyhjäksi kun sen käynnistää? Ainakin oman testauksen mukaan noin on.

Mutta miten saisin kontin data tiedostot kirjoitettua host voluumille silloin kun kontti käynnistetään?
 
Mutta miten saisin kontin data tiedostot kirjoitettua host voluumille silloin kun kontti käynnistetään?
Ei kai tuossa ole mitään sen ihmeellisempää kuin

1) määrität volumen sille kontille, joka viittaa johonkin isäntäkoneen polkuun ja
2) määrität ne isäntäkoneen polun hakemisto-oikeudet niin, että ko. kontin käyttäjällä on oikeus kirjoittaa hakemistoon.

En ihan saanu tolkkua tuosta ekasta kappaleesta, mutta noin varmaan voi käydä, jos se mounttaus ei onnistu ja/tai se kontti ei onnistu kirjoittamaan ko. polkuun. Ne kontin lokit voi kurkata, että tuleeko esim. jotain "permission denied" erroria, kun kontti koittaa jotain kirjoitusoperaatiota tehdä, mutta ei tuossa muuten kai pitäs tarvita mitään muuta kuin nuo edelliset.

muoks. vai ymmärsinköhän tätä edes oikein, että mikä tää tarve on..
 
Ei kai tuossa ole mitään sen ihmeellisempää kuin

1) määrität volumen sille kontille, joka viittaa johonkin isäntäkoneen polkuun ja
2) määrität ne isäntäkoneen polun hakemisto-oikeudet niin, että ko. kontin käyttäjällä on oikeus kirjoittaa hakemistoon.

En ihan saanu tolkkua tuosta ekasta kappaleesta, mutta noin varmaan voi käydä, jos se mounttaus ei onnistu ja/tai se kontti ei onnistu kirjoittamaan ko. polkuun. Ne kontin lokit voi kurkata, että tuleeko esim. jotain "permission denied" erroria, kun kontti koittaa jotain kirjoitusoperaatiota tehdä, mutta ei tuossa muuten kai pitäs tarvita mitään muuta kuin nuo edelliset.

muoks. vai ymmärsinköhän tätä edes oikein, että mikä tää tarve on..
Imagessa on siis tiedostoja kuten index.html mutta en ole saanut laitettua vielä niitä host voluumiin silloin kun kontti luodaan. Kontissa ei edes pyöri mikään vaan se on pelkkä cmd sleep infinity, joten logejakaan ei ole.

Joku parempikin ratkaisu varmaan olisi, mutta ainakin tällä tavalla kontti on päällä jatkuvasti jotta watchtower voi sen päivittää kun gh actions päivittää imagen docker hubissa.
 
Imagessa on siis tiedostoja kuten index.html mutta en ole saanut laitettua vielä niitä host voluumiin silloin kun kontti luodaan. Kontissa ei edes pyöri mikään vaan se on pelkkä cmd sleep infinity, joten logejakaan ei ole.

Joku parempikin ratkaisu varmaan olisi, mutta ainakin tällä tavalla kontti on päällä jatkuvasti jotta watchtower voi sen päivittää kun gh actions päivittää imagen docker hubissa.
Joo, en näemmä ymmärrä, mitä tässä on tarkoitus tehdä...

Väännätkö vielä rautalangasta, että miks nuo tiedostot on buildattu sinne imageen? Koska jos sää haluat näkyvyyden niihin tiedostoihin sekä isäntäkoneelta että kontista ja haluat, että ne tiedostot on riippumattomia kontin elinkaaresta, niin minusta ne pitäs sijoittaa sinne isäntäkoneelle polkuun, jonka määrittelet volumeksi sille kontille, eikä buildata sinne imageen.
 
Joo, en näemmä ymmärrä, mitä tässä on tarkoitus tehdä...

Väännätkö vielä rautalangasta, että miks nuo tiedostot on buildattu sinne imageen? Koska jos sää haluat näkyvyyden niihin tiedostoihin sekä isäntäkoneelta että kontista ja haluat, että ne tiedostot on riippumattomia kontin elinkaaresta, niin minusta ne pitäs sijoittaa sinne isäntäkoneelle polkuun, jonka määrittelet volumeksi sille kontille, eikä buildata sinne imageen.
Niin, tarkoitus on tosiaan että imagen tiedostot menee konttiin ja kontti kirjoittaa ne tiedostot host koneen polkuun. Jos image päivittyy niin kontti kirjoittaisi tiedostot uudestaan host polkuun.

No täytyy vielä tämän kanssa vielä säätää.

EDIT:

Jos jotain kiinnostaa niin ratkoin ongelman, tälläin kun tosiaan docker ei voi suoraan laittaa filuja bind mounttiin contista. Eli dockerfile lataa tälläisen skriptin lopuksi:

YAML:
#!/bin/sh

DIRECTORY="/static"

if [ -d "$DIRECTORY" ]; then
  rm -rf $DIRECTORY
fi

mkdir -p static  && cp -r /container/. /static  && sleep infinity
 
Viimeksi muokattu:
^ joo, ei siinä oo mitään epäselvää, etteikö noin voi tehdä, mutta edelleen kiinnostaa miksi :D
 
Halusin vaan saada "pipelinen" jossa staattinen sivusto buildataan github actioneissa ja image jossa uudet filut on päivitetään docker hubiin. Watchtower päivittää sen vps:n puolella koska kontti on kuitenkin päällä, joten se huomaa päivittää sen ja kontti sitten päivittää tuon skriptin avulla staatttisen sivun filut reverse proxyn file serveriin. Sitten saitti on taas päivitetty.

Paras tapa olisi tietty varmaan jos gh actions, lataisi filut suoraan serverille jollain rsyncillä etc. Mutta en tiedä niistä mitään niin tein tutuilla tavoilla :).
 
Viimeksi muokattu:
Paras tapa olisi tietty varmaan jos gh actions, lataisi filut suoraan serverille jollain rsyncillä etc. Mutta en tiedä niistä mitään niin tein tutuilla tavoilla :).
No vähän kummallinen konstruktio tuo on, että buildataan konttia kamoille, joita ei koskaan ajeta kontissa ja sen kontin kautta puljataan tiedostoja jonnekin remote serverille..

En oo joutunu Githubin kanssa julkaisujuttuja väsään, mutta mitä nyt vois varmaan tehdä, niin whitelistaa nuo Githubin käyttämät IP:t, näkee ilm. täältä https://api.github.com/meta, ja sallii portin 22 sinne serverille em. IP:istä. Muuten sinne serverille tuleva ylimääräinen ingress liikenne / portit syytä olla blokattuna.

Sitten vaan pipelinessä työntää scp:llä ne versionhallinnassa muuttuneet filut serverille, joka niitä tarvittee. Autentikaatiossa tarvittavan avaimen saanee varmaan johonkin Githubin secreteihin, mistä arvon voi lukea pipelinessä.
 
Viimeksi muokattu:
Jos itse käyttäisin kontteja ja watchtoweria tuohon, servaisin ne fileet vaan suoraan kontista johon reverse proxy (joka sekin todennäköisesti olisi omassa kontissan) viittaa -> kun kontti päivittyy registryssä päivittyy saitti buildin jälkeen.

Kun kerran käyttää kontteja, niin voisi niitä mielestäni hyödyntää koko matkalta.
 
Yks mikä ois kanssa varsin simppeli laittaa pystyyn, ois hostata tuo sivu AWS S3:ssa. Jos tuo on vaan siis joku staattinen sivu. Eikä varmaan maksaiskaan oikein mitään.

Muutama hassu resurssi terraformeihin ja bucketin luonti, määrittelee pääsynhallinnan haluamakseen ja tekee itelleen avaimet, joilla oikeudet bucketiin (eikä muualle). Sen jälkeen sivuston päivitys ois tyyliin vaan buildaus + one lineri aws clientillä CI jobissa. Tarvittavat salaisuudet saa tässäkin Githubin secreteihin.
 
Ja AWS:n secretejä ei sinne kannata tunkea. Oikeaoppisempi tapa on käyttää OpenID Connectia: Configuring OpenID Connect in Amazon Web Services - GitHub Docs

Eli ei tarvitse tallentaa yhtään salaisuutta GitHubiin, eikä luoda AWS:ään käyttäjää, vaan ainoastaan rooli jolla rajatut oikeudet.

(Ja tämän kaiken saa konffattua Terraformilla).
Joo, aina parempi, jos Github tarjoaa tuommoisen, joskaan en ite välttämättä ois niin vainoharhainen, että sen hyvin rajatuin oikeuksin luodun käyttäjän avaimia ahdistais laittaa Githubin secreteihinkään. Jossain omassa harrastekäytössä varmaan ihan sama ja enemmän siitä kiinni paljon jaksaa nähdä vaivaa..

Koska jonkun verran vaatii näemmä AWS:n päässä ymmärrystä IAM:sta ennen kuin niitä terraformejaan voi kirjoittaa ja siitä CI jobista tulis pykälän monimutkaisempi, kun eka tarvii assumoida rooli ja ottaa talteen avaimet + session token, ennen kuin voi komentaa bucketia, mutta joo, varmaan toimii hyvin tuollaikin.
 
Viimeksi muokattu:
Joo, aina parempi, jos Github tarjoaa tuommoisen, joskaan en ite välttämättä ois niin vainoharhainen, että sen hyvin rajatuin oikeuksin luodun käyttäjän avaimia ahdistais laittaa Githubin secreteihinkään. Jossain omassa harrastekäytössä varmaan ihan sama ja enemmän siitä kiinni paljon jaksaa nähdä vaivaa..

Koska jonkun verran vaatii näemmä AWS:n päässä ymmärrystä IAM:sta ennen kuin niitä terraformejaan voi kirjoittaa ja siitä CI jobista tulis pykälän monimutkaisempi, kun eka tarvii assumoida rooli ja ottaa talteen avaimet + session token, ennen kuin voi komentaa bucketia, mutta joo, varmaan toimii hyvin tuollaikin.

Kumpikin toimii kyllä, mutta salasanattomuudesta on selviä etuja ihan ilman vainoharhojakin. Salasanaa ei tarvitse keksiä, syöttää, kopioda, rotatoida koskaan, tai unohtaa poistaa jostain. Ja tuollainen on ihan perustavasti turvallisempi tapa hoitaa oikeudet eli hyvä muutoinkin totutella tuollaiseen vaikkea jossain omassa harrasteproggiksessa niin isot panokset olisikaan.

Se GH:n pääty oli hyvin helppo konffata käyttäen actionia "aws-actions/configure-aws-credentials" eikä se juuri muuta sitä workflowta. Terraformissa sai säätää vähän enemmän että sai homman toimimaan. Mutta ei nyt isompaa magiaa tarvinnut.
 
Kumpikin toimii kyllä, mutta salasanattomuudesta on selviä etuja ihan ilman vainoharhojakin. Salasanaa ei tarvitse keksiä, syöttää, kopioda, rotatoida koskaan, tai unohtaa poistaa jostain. Ja tuollainen on ihan perustavasti turvallisempi tapa hoitaa oikeudet eli hyvä muutoinkin totutella tuollaiseen vaikkea jossain omassa harrasteproggiksessa niin isot panokset olisikaan.
Joo, siitä ehdottomasti samaa mieltä, että yleisesti hyvä opetella hyvät käytännöt, mutta oikeasti tässä keississä minusta ihan sama. Käyttäjä, jolla ei ole mitään muita oikeuksia kuin bucket policyssä oikeus muutamaan operaatioon yhteen buckettiin ja bucketissa hostataan muutenkin julkisesti saatavilla olevaa sivua. Ja jos joku pääsee tilin secreteihin, niin varmaan pääsee myös ajamaan jobeja, jolloin saa kyllä tehtyä nuo avaimet itelleen.

AWS:n avaimia ei tarvii keksiä ite eikä CI:ssä tallennuksen jälkeen syöttäkään mihinkään, mutta rotatoida ois toki hyvä, mikä sekin kyllä aika raskasta harrastehommissa, mutta toi rotatointi on parin kolmen minuutin homma, kun käy IAM:ssä disabloimassa vanhan ja luo uuden. Varmaan tuohon saa rakennettua itelleen hälynkin, en jaksa tarkistaa, mutta ihmettelen, jos ei onnistuis.

Kirjoitin edellisen vähän niinku siitä kulmasta, ettei AWS oo tuttua. Jos on ja tuollaisen on kertaalleen opetellut, niin sitten vaan kopipastella paikalleen, niin kuin itekin teen, jos vastaavaa konstruktiota jossain tarviin. Tutuimmassa prokkiksessa on tosin luvitettu asioita suureksi osaksi EC2 runnerin instance rolen avulla.
 
Vähän aihetta sivuten, saako VSCoden References näkymän näyttämään funktion/interfacen (tms) nimen mistä reffi löytyy joko listauksessa tai valitun referenssin esikatseluikkunan yläosassa? Tai koko breadcrumbsin (eli tiedostonimen alla olevan "src > components > file.ts > IJotain")?
 
Miten tämä menisi helposti Visual Basicilla? Keksin vain kauhean hankalia tapoja ..

Eli laita ruudukkoon nolla, jos
- sarakenumero <= rivinumero JA rivi+sara <= 10
- jos jompikumpi ehto ei toteudu, älä laita mitään arvoa soluun

Täytin nollat esimerkkuruudukkoon käsin, oikea ruudukko on paljon suurempi.

Ruudukon vasen ylänurkka on Range("D4") haluaisin käyttää sitä jonkinlaisena referenssinä, kun rivien ja sarakkeiden määräkin voi joskus vaihdella ...
 

Liitteet

  • D4.png
    D4.png
    5,4 KB · Luettu: 40
Miten tämä menisi helposti Visual Basicilla? Keksin vain kauhean hankalia tapoja ..

Eli laita ruudukkoon nolla, jos
- sarakenumero <= rivinumero JA rivi+sara <= 10
- jos jompikumpi ehto ei toteudu, älä laita mitään arvoa soluun

Täytin nollat esimerkkuruudukkoon käsin, oikea ruudukko on paljon suurempi.

Ruudukon vasen ylänurkka on Range("D4") haluaisin käyttää sitä jonkinlaisena referenssinä, kun rivien ja sarakkeiden määräkin voi joskus vaihdella ...
Laita oma koodi, niin eiköhän täällä refaktoroida, jos sille potentiaalia on :) Ketjun kannaltakin mielenkiintoisempaa.
 
Eli tuo D4 referenssi tökkii, lisäksi tähän voisi olla parempikin tapa ehkä ..

' rivejä tällä kertaa a = 10 'sarakkeita tällä kertaa b = 5 for rivi = 1 to a for sara = 0 to b if rivi >= sara and rivi+sara <= a then range("D4") ??? .value = 0 next next
 
Joo tämä jo ratkesi range("D4").offset(rivi-1,sara).value = 0

Hiton VB, joka kerralla on eri kieli kun pitää jotakin tehdä ja en osaa yhtäkään.
 
Onko valmista ohjelmaa mikä muokkaisi .txt tai .prn tiedostosta tietyt rivit nollaksi? Minulla on tiedostoja jotka joudun käsin käymään läpi notepadissa ja virheitä ei saisi tulla, riveillä on aina sama "osoite" ja kohta mistä ne pitää muuttaa.
Tiedostossa on siis tuhansia rivejä ja muutettavat rivit ovat peräkkäin n.10 kpl, eli ei missä sattuu väleissä. Helpoin olisi joku ohjelma mihin valitaan input file, tiedosto muutetaan ja valitaan muutetulle tiedostolle uusi nimi.
Voisi olla ihan mielenkiintoinen tehdä itsekkin ohjelma, mutta ei ole ohjelmoinnista mitään kokemusta. Onko tälläinen ohjelma vaikea tehdä?

Esim.
(Alkuperäinen) (Muutettu)
FF11 123 123 = FF11 000 000
FF22 123 432 = FF22 000 000
FF33 123 234 = FF33 000 000
 
Onko valmista ohjelmaa mikä muokkaisi .txt tai .prn tiedostosta tietyt rivit nollaksi? Minulla on tiedostoja jotka joudun käsin käymään läpi notepadissa ja virheitä ei saisi tulla, riveillä on aina sama "osoite" ja kohta mistä ne pitää muuttaa.
Tiedostossa on siis tuhansia rivejä ja muutettavat rivit ovat peräkkäin n.10 kpl, eli ei missä sattuu väleissä. Helpoin olisi joku ohjelma mihin valitaan input file, tiedosto muutetaan ja valitaan muutetulle tiedostolle uusi nimi.
Voisi olla ihan mielenkiintoinen tehdä itsekkin ohjelma, mutta ei ole ohjelmoinnista mitään kokemusta. Onko tälläinen ohjelma vaikea tehdä?

Esim.
(Alkuperäinen) (Muutettu)
FF11 123 123 = FF11 000 000
FF22 123 432 = FF22 000 000
FF33 123 234 = FF33 000 000


Oletko kokeillut Notepad++? Siinä on paljon mahdollisuuksia tekstin muokkaukseen.
 
Onko valmista ohjelmaa mikä muokkaisi .txt tai .prn tiedostosta tietyt rivit nollaksi? Minulla on tiedostoja jotka joudun käsin käymään läpi notepadissa ja virheitä ei saisi tulla, riveillä on aina sama "osoite" ja kohta mistä ne pitää muuttaa.
Tiedostossa on siis tuhansia rivejä ja muutettavat rivit ovat peräkkäin n.10 kpl, eli ei missä sattuu väleissä. Helpoin olisi joku ohjelma mihin valitaan input file, tiedosto muutetaan ja valitaan muutetulle tiedostolle uusi nimi.
Voisi olla ihan mielenkiintoinen tehdä itsekkin ohjelma, mutta ei ole ohjelmoinnista mitään kokemusta. Onko tälläinen ohjelma vaikea tehdä?

Esim.
(Alkuperäinen) (Muutettu)
FF11 123 123 = FF11 000 000
FF22 123 432 = FF22 000 000
FF33 123 234 = FF33 000 000
Minkälaisia ne rivit on, joita ei muokata? Eli siis millä logiikalla pitäis valita rivit, johon tehdään toi muutos?
 
Viimeksi muokattu:
Jonkun reg expressionin voi tehdä jos siinä on joku kasvaa ja monet teksti editorit tukee sillä search and replace all.
 
Kokeilin notepad++ tuota etsi ja korvaa, varmaan jollain säädöllä saisi toimivan, menee nyt vähän rikki rivit. Sitä en vielä löytänyt että saisi sen tallennettua automaattiseksi toiminnoksi, että ei aina tarvitsisi käsin syöttää. Käytännössä nyt nopeampi copy pastella valmiista tiedostosta leikata ja liittää.

Tuo reg expression vaikuttaa juuri siltä mitä haen, pitää siihen perehtyä jossain vaiheessa.

Kiitos hyvistä vastauksista.
 
Koodi:
# cat inFile.txt
FF11 123 234
FF22 123 234
FF33 123 123
FF44 123 432
FF55 123 234
# awk '{ if ($1 ~ /^FF[44-55]/) {$2 = "000"; $3 = "000"} }; { print }' inFile.txt > outFile.txt
# cat outFile.txt
FF11 123 234
FF22 123 234
FF33 123 123
FF44 000 000
FF55 000 000
Tämä muokkaa kaksi viimeistä saraketta nolliksi ensimmäisen sarakkeen numeroiden ollessa välillä 44-55
 
Joo, sed toinen, joka lienee näppärämpi kuin koodailla itse mitään ja tukee kanssa regexejä tuossa etsittävässä patternissa.

Syntaksi pykälän simppelimpi:
Koodi:
sed 's/etsittävä/korvattu/g' input.txt > output.txt

Lähinnä jäis mietittäväksi, millainen regex mätsää noihin muokattaviin riveihin tai voi myös vaan käsitellä erikseen kaikki vaihtoehdot, jos niitä ei oo paljoa tyyliin:
Koodi:
sed 's/pattern1/korvattu; s/pattern2/korvattu' input.txt > output.txt
 
Viimeksi muokattu:
Huomenta, olen tammikuussa aloittanut ohjelmoinnin opiskelun. Nyt tuli vastaan seinä, miksi koodini ei toimi? Kielenä C#.


Visual Studio 2022 antaa seuraavanlaista tulosta:

1707713766083.png
 
Huomenta, olen tammikuussa aloittanut ohjelmoinnin opiskelun. Nyt tuli vastaan seinä, miksi koodini ei toimi?

Tuntematta alustaa veikkaisin että "random" sillä on kaikkea muuta kuin random, ja nyt kun luot uuden Random-olion joka heittokutsulla ja otat siitä ensimmäisenä tarjolla olevan luvun, on se joka kerralla sama.
 
Tuntematta alustaa veikkaisin että "random" sillä on kaikkea muuta kuin random, ja nyt kun luot uuden Random-olion joka heittokutsulla ja otat siitä ensimmäisenä tarjolla olevan luvun, on se joka kerralla sama.

Miten tuon Random-olion voisi tehdä paremmin?
 
Miten tuon Random-olion voisi tehdä paremmin?

Koska kyseessä selvästi jokin harjoitustehtävä niin en liian valmista ratkaisua halua antaa, mutta ensimmäiseksi tutkisin Random-luokan dokumentointia ja selvittäisin miten se alustetaan seedillä, ja sitten koittaisin löytää tavan saada seediksi luvun joka olisi suurella varmuudella erilainen joka kerta. Ja ehkäpä sen olion voisi luoda yhden kerran ja hakea vain seuraavan siltä heittäessä.
 
Minäkään oikein tunne C#:a kovin hyvin, mutta systeemiaika vaikuttaisi olevan Random-luokan default seed (eli pitäisi kyllä olla joka kerta eri).

Voihan tuota Noppa-luokkaa muuttaa niin, että tekee sille konstruktorin, joka ottaa parametrina (kerran alustetun) Random-luokan.

Mut yleisesti vastaavissa ongelmissa kannattaa opetella käyttämään IDE:n breakpointeja tai debug-lokitusta (yksinkertaisimmillaan ihan tulostuskutsuja). Tuolta heitä metodista esim. tulostaa, mitä saatiin sivuiksi ja mitä metodi palauttaa. Break pointin sopivaan kohtaan asettamalla näkis sit yleisemmin, mitkä muuttujien arvot on, niin selviää se, ettei muuttujien arvot ole menneet jossain kohtaa sekaisin, kun niitä on tuossa jonkin verran plus tuota kaikenlaista String - Int -konversiota.
 
Viimeksi muokattu:
Jos systeemiaika on tuossa siemen joka iteraatiolla ja jos luuppia ajetaan tarpeeksi nopeasti, niin se siemen on aina sama (koska tietokoneen ajalla on rajallinen resoluutio) kun luodaan uusi Random-olio ja näin tulee sama tulos. Oletan, että kun sekunnin päästä ajaa uudelleen, on tulos jotain muuta kuin tuo 2.

Tosiaan oikeaoppinen tapa on se, että luodaan se Random-olio vain kerran, ja sitten aletaan ottaa siitä samasta oliosta niitä satunnaislukuja. Voisko siitä tehdä staattisen muuttujan tuolle Noppa-luokalle? Tai sitten kutsuja passaa Random-olion aina kun sitä käytetään.
 
Jos systeemiaika on tuossa siemen joka iteraatiolla ja jos luuppia ajetaan tarpeeksi nopeasti, niin se siemen on aina sama (koska tietokoneen ajalla on rajallinen resoluutio) kun luodaan uusi Random-olio ja näin tulee sama tulos. Oletan, että kun sekunnin päästä ajaa uudelleen, on tulos jotain muuta kuin tuo 2.

Juurikin näin. Ohjelma antaa oikean tuloksen kun käytän oikeassa kohtaa breakpointteja.

Tosiaan oikeaoppinen tapa on se, että luodaan se Random-olio vain kerran, ja sitten aletaan ottaa siitä samasta oliosta niitä satunnaislukuja. Voisko siitä tehdä staattisen muuttujan tuolle Noppa-luokalle? Tai sitten kutsuja passaa Random-olion aina kun sitä käytetään.

Pitää kokeilla, kts vinkeistä.
 
C#:
public class Noppa
    {
        private static readonly Random rnd = new Random();
        public int Heita(int sivut)
        {
           return rnd.Next(1, sivut + 1);
        }
    }

Ylläolevalla koodilla lähti toimimaan, kts kaikille vinkeistä ja vihjeistä.
 
Miten en jotenkin vieläkään jaksa uskoa, että tuo C#:n Random-luokka ois noin kökösti tehty.. ei tuossa ole Javalla tehtynä mitään ongelmaa tulostaa loopissa (pseudo)satunnaislukuja niin, että alustat joka iteraatiolle uuden Random-instanssin.

Koodi:
  public int heita() {
    var rnd = new Random();
    return rnd.nextInt(1, 4);
  }

  public static void main(String[] args) {

    var noppa = new Noppa();
    for (int i = 0; i < 10; i++) {
      System.out.println(noppa.heita());
    }
  }

Output:

Koodi:
3
3
2
1
3
3
3
2
1
3

Tuossa ilm. C# Random-luokan sorsat, mutta ei riitä nyt aika tai ymmärryskään lonkalta lähteä purkamaan, mitä kaikkea tuo tosiasiassa tekee:

 
Jos systeemiaika on tuossa siemen joka iteraatiolla ja jos luuppia ajetaan tarpeeksi nopeasti, niin se siemen on aina sama (koska tietokoneen ajalla on rajallinen resoluutio) kun luodaan uusi Random-olio ja näin tulee sama tulos. Oletan, että kun sekunnin päästä ajaa uudelleen, on tulos jotain muuta kuin tuo 2.

Näinpä, tämän vuoksi pseudorandom seedinä aika usein käytetään esim. milli- tai jopa nanosekuntiresoluution systeemiaikaa jos ei käytettävissä ole "aitoa" randomia seediksi.
 
^ varmasti tulee loopinkin sisällä eri arvot, jos tulostelee jotain käyttöjärjestelmän epoch aikaleimaa jokaiselta iteraatiolta.

muoks. niin ja yllä tosiaan nuo sorsat, jos joku haluaa lähteä ihmetteleen, mitä tuo C#:n luokka tekee.
 
C# Random käyttää seedinä Environment.TickCount Environment.TickCount Property (System)

The value of this property is derived from the system timer and is stored as a 32-bit signed integer. Note that, because it is derived from the system timer, the resolution of the TickCount property is limited to the resolution of the system timer, which is typically in the range of 10 to 16 milliseconds.
 
Onko 4 merkkiä pitkä, base62 enkoodattu merkkijono (jokainen merkki aakkosista 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz) 32-bittinen? Siis kun UUIDv6 on 128-bittinen, kun siinä on 36 heksadesimaalilukua, ja yksi heksadesimaali vie 4 bittiä (32 * 1 * 4), mutta base62-kirjain vie 2 heksadesimaalia, jolloin 4 * 2 * 4 -> 32?
 
Onko 4 merkkiä pitkä, base62 enkoodattu merkkijono (jokainen merkki aakkosista 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz) 32-bittinen? Siis kun UUIDv6 on 128-bittinen, kun siinä on 36 heksadesimaalilukua, ja yksi heksadesimaali vie 4 bittiä (32 * 1 * 4), mutta base62-kirjain vie 2 heksadesimaalia, jolloin 4 * 2 * 4 -> 32?
Wikipedia näyttää että base62 olisi kuusi bittiä per merkki (ei suoraa speksiä, mutta listauksessa on kuusi bittiä per merkki), eli 1,5 hexaa tai 0,75 tavua. Käy järkeen koska muuten siinä olisi hukkatilaa.

Eli neljä merkkiä olisi 3 tavua tai 24 bittiä (4*6).

Edit:
Sekoilua

Edit2:
En saanut otetta miten uuid v6 liittyy tähän. Se on 128 bittinen arvo, joka heksoina esitettynä sisältää 32 merkkiä. base62 enkoodattuna se olisi laskelmieni mukaan 21,5 merkkiä pitkä.

Edit3:
Koska base62 sisältää 62 verran tietoa kuudessa bitissä (64) jää vähän informaatiota yli, jolloin se tekee muunnoksista hankalampia mikäli käytetään myös nuo tuo yli jäänyt data.
 
Viimeksi muokattu:
Wikipedia näyttää että base62 olisi kuusi bittiä per merkki (ei suoraa speksiä, mutta listauksessa on kuusi bittiä per merkki), eli 1,5 hexaa tai 0,75 tavua. Käy järkeen koska muuten siinä olisi hukkatilaa.

Eli neljä merkkiä olisi 3 tavua tai 24 bittiä (4*6).

Edit:
Sekoilua

Edit2:
En saanut otetta miten uuid v6 liittyy tähän. Se on 128 bittinen arvo, joka heksoina esitettynä sisältää 32 merkkiä. base62 enkoodattuna se olisi laskelmieni mukaan 21,5 merkkiä pitkä.

Edit3:
Koska base62 sisältää 62 verran tietoa kuudessa bitissä (64) jää vähän informaatiota yli, jolloin se tekee muunnoksista hankalampia mikäli käytetään myös nuo tuo yli jäänyt data.
UUID:n otin esille varmaan sillä, että siinä voi päätellä bittimäärän perusteella todennäköisyyden että se generoi duplikaatin, ja tässä yritän pienessä päässäni järkeillä että jos otan randomisti base62 -taulukosta merkkejä (chars[rand(0, 61)]), ja laitan niitä peräkkäin, niin kuinka monta niitä pitää olla että siinä on vähintään vaikkapa 24 tai 32bittiä (ja näin laskea myös sen collisio-todennäköisyyden)?
 
UUID:n otin esille varmaan sillä, että siinä voi päätellä bittimäärän perusteella todennäköisyyden että se generoi duplikaatin, ja tässä yritän pienessä päässäni järkeillä että jos otan randomisti base62 -taulukosta merkkejä (chars[rand(0, 61)]), ja laitan niitä peräkkäin, niin kuinka monta niitä pitää olla että siinä on vähintään vaikkapa 24 tai 32bittiä (ja näin laskea myös sen collisio-todennäköisyyden)?
Tarkoitatko siis että jos sinulla on 128 bittinen arvo, niin haet sitä että kuinka suurella todennäköisyydellä saat saman arvon jos rakennat arvon jonosta arvoja välillä 0-61? Se riippuu allokoitko jokaiselle arvolle täydet 6 bittiä vai sallitko kuuteen bittiin mahtuvan ylijäämän kierrättämisen eteenpäin kokonaisarvoon, jolloin saat useamman arvon mahtumaan tuohon 128 bittiin.

Jos sisällytät 6 tavun ylijäämät base62:sta menee laskenta nopeasti katsottuna jotakuinkin tämän mukaan: What is Base62 Conversion?
Jos taas käytät kuusi tavua per merkki jätät tuosta 128 tavun arvosta osan käyttämättä koska se ei ole kuudella jaollinen tai vaihtoehtoisesti otat vain kahden tavun arvoisen merkin loppuun. Onko peräkkäin laittaminen tavoitteen mukaista?

Base62 arvo ei ole jaollinen 24 tai 32 bitin maksimiarvon kanssa. Jos haluat tietää kuinka monta base62 merkkiä on arvoltaan vähintään 24 bittiä, on vastaus viisi. Kysymys ei kuitenkaan ole niin yksinkertainen, sillä neljä base62 merkkiä on arvoltaan 14 776 336, kun taas 24 bittiä on arvoltaan 16 777 216. Viisi base62 merkkiä meneekin pitkälle yli. Jos nuo noin kaksi miljoonaa väliin jäävää arvoa vielä jaetaan base62 merkeistä koostuvalle merkkijonolle saadaan huomattavasti enemmän mahdollisuuksia kuin mihin neljällä merkillä päästään. Onko tämän taustalla koulutehtävä jonka tarkoituksena on ymmärtää binääriarvoja?
 
UUID:n otin esille varmaan sillä, että siinä voi päätellä bittimäärän perusteella todennäköisyyden että se generoi duplikaatin, ja tässä yritän pienessä päässäni järkeillä että jos otan randomisti base62 -taulukosta merkkejä (chars[rand(0, 61)]), ja laitan niitä peräkkäin, niin kuinka monta niitä pitää olla että siinä on vähintään vaikkapa 24 tai 32bittiä (ja näin laskea myös sen collisio-todennäköisyyden)?
Jos kiinnostava asia on tuo lopussa suluissa oleva todennäköisyys sille että kaksi satunnaista base62 merkkijonoa ovat samat, niin eikö sen voi laskea ihan tavanomaisella todennäköisyyslaskennalla? Yhden saman merkin todennäköisyys on silloin 1/62 ja saman N merkkiä pitkän merkkijonon (1/62)^N. Tuotahan voi sitten verrata halutessa vastaavaan bittijonon todennäköisyyteen jossa yhden saman bitin todennäköisyys on 1/2. Tuosta laskimella 32 bittisten bittijonojen samanlaisuuden todennäköisyys (1/2)^32 = 2,328e-10. Sitten kokeilemalla vähintään yhtä epätodennäköinen base62 merkkijono: (1/62)^6 = 1.761e-11. Eli jo 6 base62 merkkiä pitkien merkkijonojen "yhteentörmäyksen" todennäköisyys on pienempi kuin 32 bittisten bittijonojen.
 
Jos kiinnostava asia on tuo lopussa suluissa oleva todennäköisyys sille että kaksi satunnaista base62 merkkijonoa ovat samat, niin eikö sen voi laskea ihan tavanomaisella todennäköisyyslaskennalla? Yhden saman merkin todennäköisyys on silloin 1/62 ja saman N merkkiä pitkän merkkijonon (1/62)^N. Tuotahan voi sitten verrata halutessa vastaavaan bittijonon todennäköisyyteen jossa yhden saman bitin todennäköisyys on 1/2. Tuosta laskimella 32 bittisten bittijonojen samanlaisuuden todennäköisyys (1/2)^32 = 2,328e-10. Sitten kokeilemalla vähintään yhtä epätodennäköinen base62 merkkijono: (1/62)^6 = 1.761e-11. Eli jo 6 base62 merkkiä pitkien merkkijonojen "yhteentörmäyksen" todennäköisyys on pienempi kuin 32 bittisten bittijonojen.
No sehän tässä on ongelma, etten ymmärrä mistä se bittisyys tässä tulee. Jos generoin randomisti 4 tavua (esim. js:llä window.crypto.getRandomValues(new Uint8Array(4)), saan 32 bittiä informaatiota, ja lopuksi konvertoin sen base62-merkkijonoksi, se sisältää edelleen 32 bittiä informaatiota, ja on joka kerta täsmälleen 4 merkkiä pitkä. Siis miten on mahdollista, että neljän base62 -merkin laittaminen peräkkäin eri menetelmällä yhtäkkiä onkin vain 24-bittinen? Se on tällaista kun ei ole teoriataustaa, ja järkikin juoksee välillä melkein takaperin :D
 
No sehän tässä on ongelma, etten ymmärrä mistä se bittisyys tässä tulee. Jos generoin randomisti 4 tavua (esim. js:llä window.crypto.getRandomValues(new Uint8Array(4)), saan 32 bittiä informaatiota, ja lopuksi konvertoin sen base62-merkkijonoksi, se sisältää edelleen 32 bittiä informaatiota, ja on joka kerta täsmälleen 4 merkkiä pitkä. Siis miten on mahdollista, että neljän base62 -merkin laittaminen peräkkäin eri menetelmällä yhtäkkiä onkin vain 24-bittinen? Se on tällaista kun ei ole teoriataustaa, ja järkikin juoksee välillä melkein takaperin :D
Tuo luo neljä 8 bittistä satunnaisarvoa. Jos muunnat ne base62 merkeiksi ja saat vain neljä merkkiä, tarkoittaa se että muunnos on häviöllinen. Kahdeksan bittinen (1 tavu) arvo on välillä 0-255 ja base62 on 0-61. Esim. arvo 128 kääntyisi häviöttömästi base62 merkeiksi "24" (jos nopeasti laskin oikein). Nelitavuinen arvo sitten on jo jotain aivan muuta base62:ksi käännettynä. Häviöllinen muunnos riippuu millä tavalla se on tehty.

Jos saat neljä kirjainta, voi olla että ne ovat esim. iso 8859 tai extended ASCII muodossa ja siksi vievät 8 bittiä per merkki. Uint8 kääntyykin näppärästi suoraan tuohon muotoon ilman ongelmia. Tietämättä sen tarkemmin millä tuon käännöksen teet on vaikea asiaa analysoida enempää.

EDIT:
Laskin uusiksi...
 
Viimeksi muokattu:
... tarkoittaa se että muunnos on häviöllinen...
Oikeassa olet, törmäsin tähän itsekin kun aloin miettimään miten sen merkkijonon voi dekoodata (vastaus: ei voi, koska informaatiota häviää). Sain kuitenkin ongelmaani ratkaisun (joka siis oli että kuinka monta merkkiä tarvitsee, että todennäköisyys että saa kaksi samaa on "tarpeeksi pieni" (<0.2%)) – päädyin siihen että 4 merkkiä riittää, bittimäärä oli tässä oikeastaan vain sivuseikka. Kiitos vastaajille. PS. käytin Collision Calculator -sivun laskinta todennäköisyyden laskemiseen, vaikutti se että se osasi hommansa, ja lähdekoodin silmäilyn mukaan ottaa huomioon myös syntymäpäiväongelman.
 

Statistiikka

Viestiketjuista
302 697
Viestejä
5 152 199
Jäsenet
82 208
Uusin jäsen
tovarištš

Hinta.fi

Back
Ylös Bottom