Legyen két sor? Nem fér ki:
0 2 4 6 8 10 12 14 16
1 3 5 7 9 11 13 15 17
Oké, tehát három sor lesz:
0 3 6 9 12 15
1 4 7 10 13 16
2 5 8 11 14 17
De akkor meg csak hat oszlopom van. Na most mi legyen? Esetleg változtassam meg a specfikációt, és legyenek egyenletesen az oszlopok? [vagyis lehessen több rövid oszlop, de a hosszú és rövid oszlopok magassága közötti különbség legyen egy]
c=7 c=8
0 3 6 9 12 14 16 0 3 6 8 10 12 14 16
1 4 7 10 13 15 17 1 4 7 9 11 13 15 17
2 5 8 11 -- -- -- 2 5 -- -- -- -- -- --
- NevemTeve blogja
- A hozzászóláshoz be kell jelentkezni
Hozzászólások
Legyen egymasra meroleges 7 piros vonal! De zold es atlatszo tintaval!
A strange game. The only winning move is not to play. How about a nice game of chess?
- A hozzászóláshoz be kell jelentkezni
Annak, aki nem ismerne: https://www.youtube.com/watch?v=BKorP55Aqvg
A strange game. The only winning move is not to play. How about a nice game of chess?
- A hozzászóláshoz be kell jelentkezni
thx
- A hozzászóláshoz be kell jelentkezni
Nézd meg hogy az `ls -v` mit csinál. Nekem úgy tűnik hogy az is a kevesebb oszlopra szavaz.
Az alternatív specifikáció ötleted nekem nem tetszik, nem tűnik tipikus, jól ismert viselkedésnek.
- A hozzászóláshoz be kell jelentkezni
Durván becsülve azt mondanám, hogy c>2 esetén c(c-1)/2 (c-1)(c-2)/2 [szerk: javítva] olyan szám van, amit nem lehet c oszlopban szépen elrendezni, ezek közül a legnagyobb az n=(c-1)^2 [szerk: meg még az n<c esetek, amit nem számoltam bele a fentibe]
Kipróbálva a lehetőségeket, a megkerülő megoldások közül az oszlopok számának csökkentése tűnik szebbnek; sőt, akár azzal is kezdhetjük, hogy ha az n kisebb a c néhányszorosánál, akkor szintén csökkentjük az oszlopok számát, hogy ne legyen túl széles a táblázat.
- A hozzászóláshoz be kell jelentkezni
Jó feladat. Az a helyzet, hogy nincs mindig megoldása. Ugyanis amit valójában elvársz, az a következő: azt várod el, hogy az első maradékos osztás adjon nulla maradékot, vagy a második maradékos osztás adjon nemnulla maradékot. (Ezeket a maradékos osztásokat mindjárt leírom formálisan is.) És van olyan n és c, hogy egyik elvárás sem teljesül.
Tehát formálisan (az alábbiakban n, c, q, q2, r és r2 mind egész számok):
- Első körben azt a maradékos osztást nézed, hogy n = q * c + r, ahol adott n>0 a tételek száma, adott c>0 a teljes oszlopok száma, keresett q>=0 a hányados (sorok száma a teljes oszlopokban), és keresett c>r>=0 a maradék (az utolsó, nem teljes oszlopban lévő sorok száma -- maradék lévén ez kisebb, mint az osztó; ha már annyi sor szerepelne az utolsó, nem teljes oszlopban, mint ahány teljes oszlop van, akkor a hányados nőne meg, vagyis eggyel több sor lenne a teljes oszlopokban).
Első körben azt várod el, hogy r=0 legyen; ekkor kapsz egy szép mátrixot, pontosan c oszloppal, és q sorral. (És ekkor rögtön adódik az is, hogy q pozitív, hiszen n = q * c.)
Ha viszont r>0 adódik, akkor van egy nem teljes utolsó oszlopod is, amivel megszegted az "oszlopszám=c" elvárást, tehát át kell térnünk eggyel kisebb oszlopszámra ((c-1)-re). Itt rögtön látjuk azt is, hogy ebben az esetben c>=2 (tehát (c-1) még mindig pozitív lesz); ugyanis ha az eredeti osztó c=1 volt (összesen 1 oszlopot kértünk), akkor q=n (n sorunk lesz) és r=0 (nincs maradék -- nincs nem teljes oszlop) -- vagyis c=1 esetén nem jutottunk volna ide (ahol r>0).
- Második körben azt a maradékos osztást nézzük, hogy n = q2 * (c-1) + r2, ahol adott n>0 továbbra is a tételek száma, adott (c-1)>0 az oszlopok (eggyel csökkentett, de a fentiek szerint még mindig pozitív) száma, keresett q2>=0 hányados (a sorok száma a teljes oszlopokban), és keresett (c-1)>r2>=0 maradék (az utolsó, nem teljes oszlopban lévő sorok száma).
Pontosabban (és ezen bukik a dolog): itt azt várjuk el, hogy r2>0 legyen. Ugyanis ha r2=0, akkor nincs betöltetlen oszlop, és kapunk egy szép mátrixot (c-1) oszloppal és q2 sorral -- ami viszont ismét megszegi az eredeti "oszlopszám=c" elvárást.
Vagyis a sejtésed az (más szóval: a specifikáció feltételezése az), hogy:
∀ n, c ∈ ℕ⁺: (∃ q ∈ ℕ⁺: n = q * c) ∨ (∃ q₂ ∈ ℕ, (c - 1) > r₂ ∈ ℕ⁺: n = q₂ * (c-1) + r₂)
Mivel ez egy olyan elsőrendű logikai állítás, amely univerzális kvantorral kezdődik, azért a cáfolatához elég egy ellenpéldát találni. Formálisan, a sejtés negáltja úgy néz ki, hogy először az egész elé kiragasztunk egy tagadást:
¬∀ n, c ∈ ℕ⁺: (∃ q ∈ ℕ⁺: n = q * c) ∨ (∃ q₂ ∈ ℕ, (c - 1) > r₂ ∈ ℕ⁺: n = q₂ * (c-1) + r₂)
Aztán a logikai "nem" operátort bevisszük az univerzális kvantoron belülre (amitől az egzisztenciális kvantorrá változik, a kvantált predikátum pedig negálódik):
∃ n, c ∈ ℕ⁺: ¬((∃ q ∈ ℕ⁺: n = q * c) ∨ (∃ q₂ ∈ ℕ, (c - 1) > r₂ ∈ ℕ⁺: n = q₂ * (c-1) + r₂))
Azután a De Morgan azonossággal a negálást szétosztjuk a logikai "vagy"-on (amitől a "vagy" "és"-sé változik, az operandusai pedig negálódnak):
∃ n, c ∈ ℕ⁺: ¬(∃ q ∈ ℕ⁺: n = q * c) ∧ ¬(∃ q₂ ∈ ℕ, (c - 1) > r₂ ∈ ℕ⁺: n = q₂ * (c-1) + r₂)
Ismét a kvantoros játék:
∃ n, c ∈ ℕ⁺: (∀ q ∈ ℕ⁺: n ≠ q * c) ∧ (∀ q₂ ∈ ℕ, (c - 1) > r₂ ∈ ℕ⁺: n ≠ q₂ * (c-1) + r₂)
Ha ezt az állítást sikerül kielégíteni, akkor a sejtést megcáfoltuk.
Az általad adott n=18, c=7 számpár "létezik", és kielégíti a sejtés negáltját; vagyis cáfolja a sejtést:
(∀ q ∈ ℕ⁺: 18 ≠ q * 7) ∧ (∀ q₂ ∈ ℕ, 6 > r₂ ∈ ℕ⁺: 18 ≠ q₂ * 6 + r₂)
Ennek a konjunkciónak mindkét operandusa igaz, ugyanis:
- a 18 nem osztható 7-tel (bármely pozitív egésszel szorozzuk a 7-et, nem lesz a szorzat 18), valamint
- a 18-at 6-tal osztva 0 a maradék, ami pedig nem eleme az ℕ⁺ halmaznak (ha q₂ értéke 0, 1 vagy 2, akkor r₂ értéke rendre 18, 12, 6, amelyek egyike sem elégíti ki a 6>r₂ követelményt; ha q₂ értéke 3, akkor r₂=0, ami nem eleme az ℕ⁺ halmaznak; ha pedig q₂>3, akkor r₂ negatív, így nem eleme az ℕ⁺ halmaznak).
Összefoglalva: pontosan c oszloppal nem mindig megoldható a feladat; lehet, hogy (c-1) oszlopú mátrixot fogsz kapni. És ez az eset akkor áll fenn, ha c nem osztója n-nek, (c-1) viszont osztója n-nek.
- A hozzászóláshoz be kell jelentkezni
> ez az eset akkor áll fenn, ha c nem osztója n-nek, (c-1) viszont osztója n-nek.
Először én is azt gondoltam, hogy ilyen egyszerű a szabály, de itt egy ellenpélda: legyen n=102, c=7, c-1=6. Ekkor r=intsup(102/7)=15, tehát az első 6 oszlopban 6*15 tétel lesz, az utolsóban a maradék: 102-6*15=102-90=12
c=7 esetén a legnagyobb problémás érték az n=36
PS: `intsup` jelöli itt a felső egészrészt, más néven`ceil`
- A hozzászóláshoz be kell jelentkezni
itt egy ellenpélda: legyen n=102, c=7
Igazad van:
0 1 2 3 4 5 6
0 000 015 030 045 060 075 090
1 001 016 031 046 061 076 091
2 002 017 032 047 062 077 092
3 003 018 033 048 063 078 093
4 004 019 034 049 064 079 094
5 005 020 035 050 065 080 095
6 006 021 036 051 066 081 096
7 007 022 037 052 067 082 097
8 008 023 038 053 068 083 098
9 009 024 039 054 069 084 099
10 010 025 040 055 070 085 100
11 011 026 041 056 071 086 101
12 012 027 042 057 072 087 -
13 013 028 043 058 073 088 -
14 014 029 044 059 074 089 -
Nézzük akkor negatív maradékkal:
- Először (szokásos maradékos osztás): n=q*c+r; 0<=r<c adódik.
Ha r=0, akkor készen vagyunk (teljes téglalapot kaptunk).
- Egyébként n = q*c + r + (c - c) = (q+1)*c + (r - c) = (q+1)*c - (c - r) = (q+1)*(c-1) + ((q+1) - (c - r))
Ez a megfogalmazás azt fejezi ki, hogy a sorok számát eggyel megnöveljük ((q+1)-re), melynek hatására az utolsó oszlopban a (q+1) elemből (c-r) elem hiányozni fog.
Ez a módszer jól működik a példádon (q=14, q+1=15, r=4; az utolsó oszlop 15 eleméből c-r=7-4=3 elem hiányzik).
Ugyanakkor általában véve ezzel a módszerrel is baj van. A 2. lépésnél az utolsó oszlopban (q+1) elem fér el, és ebből (c-r) hiányzik -- az a baj, hogy a megmaradó elemek száma akár negatív is lehet, így az egész oszlop eltűnik.
Például legyen n=22, c=7. Ekkor q=3, r=1 (n=q*c+r; 22=3*7+1). A 7*3-as kezdeti táblázatba nem fér be 22 elem, 1 kimarad. A 2. lépés szerint legyen q+1=4 sor. Ennek hatására a táblázatba 7*4=28 elem fér be. Nekünk viszont csak 22 elemünk van, így az utolsó oszlopból 6 elem hiányzik. Igen ám, de az oszlopok magassága 4 elem, tehát az egész utolsó oszlop eltűnik -- nem lett meg a 7 oszlopunk. Az a baj, hogy a ((q+1) - (c - r)) különbség nem pozitív itt: (3+1) - (7 - 1) = 4-6 = (-2).
- A hozzászóláshoz be kell jelentkezni
Rövidesen ilyesmi:
q = intsup(n/c)
r = n - q*(c-1)
gond akkor van, ha r<=0
Most tegyük fel, hogy n >= c
, és n%c ≠ 0
, kérdés, hogy r = n-intsup(n/c)*(c-1)
mikor lesz nempozitív.
mondjuk n = Ac+B
, ahol B=n%c>0
, és A>0
, ekkor intsup(n/c) = A+1
,
r = n-(A+1)(c-1) = Ac + B - Ac - c + A +1
Vagyis r<=0
akkor teljesül, ha B+A+1 <= c
, avagy B+A < c
Ilyen eset
(c-1)(c-2)/2
van [ezt fentebb rosszul számoltam], a legnagyobb az A=c-2, B=1, n=(c-1)^2
- A hozzászóláshoz be kell jelentkezni
Rövidesen ilyesmi:
q = intsup(n/c)
r = n - q*(c-1)
gond akkor van, har<=0
Most tegyük fel, hogy
n >= c
, ésn%c ≠ 0
, kérdés, hogyr = n-intsup(n/c)*(c-1)
mikor lesz nempozitív.mondjuk
n = Ac+B
, aholB=n%c>0
, ésA>0
, ekkorintsup(n/c) = A+1
,
r = n-(A+1)(c-1) = Ac + B - Ac - c + A +1
Vagyis
r<=0
akkor teljesül, haB+A+1 <= c
, avagyB+A < c
Ilyen eset
(c-1)(c-2)/2
van [ezt fentebb rosszul számoltam], a legnagyobb azA=c-2, B=1, n=(c-1)^2
Végigszámoltam: ez jó!
Szövegesen, a módszer úgy dolgozik, hogy az osztásból származó oszloponkénti sorok számát felfelé kerekíti, és azt a feltételt keresi, amikor emiatt a felfelé kerekítés miatt az utolsó oszlop kiürül (eltűnik). Ez pedig ugyanaz az eset, mint amit én a negatív maradékos módszernél felírtam az utolsó oszlop eltűnéséhez (-> ha nem egzakt az osztás, akkor a sorok számát eggyel növeljük).
Azóta aludtam rá egyet, és most úgy gondolom, hogy amit pozitív ill. negatív maradékos módszerekként felírtam, azok együttesen véges lépésszámmal megoldják a feladatot (aminek lehet az az eredménye, hogy pontosan c oszloppal nem lehet a táblázatot elkészíteni, csak c-1 oszloppal):
- n = q * c + r; n>0; c>0; q>=0; c>r>=0
ha r=0, akkor teljes a táblázat, kész vagyunk.
Egyébként: - megpróbáljuk a negatív maradékos módszert (sorok számának növelése 1-gyel):
n = q*c + r + (c - c) = (q+1)*c + (r - c) = (q+1)*c - (c - r) = (q+1)*(c-1) + ((q+1) - (c - r))
Ha itt a vastagon szedett ((q+1) - (c - r)) tag (az utolsó oszlop elemeinek száma) pozitív, akkor az utolsó oszlop nem üres, és kész vagyunk (pontosan c oszloppal).
(Azt korábban nem írtam le, de (c-r) értékét a következőképpen becsülhetjük: mivel itt 0<r<c, azért c > (c-r) > 0. Tehát a legutolsó oszlopból minimum 1, legfeljebb (c-1) elem fog hiányozni.)
Egyébként: - megpróbáljuk a pozitív maradékos módszert (oszlopok számának csökkentése 1-gyel -- ennek az az értelme, hogy a sorok számának 1-gyel való növelésével eltűnt a c-edik oszlopunk, tehát most elindulunk abból az irányból, hogy 1-gyel kevesebb oszlopra lövünk eleve, és reménykedünk, hogy a maradék átfolyik a c-edik oszlopba):
n = q2 * (c-1) + r2
(Itt ugye tudjuk, hogy c>=2, mert c=1 esetén az 1. lépés végez, n=q és r=0 eredménnyel)
q2>=0; (c-1)>r2>=0
Ha itt r2 pozitív, akkor kész vagyunk (pontosan c oszloppal, ugyanis a c-1 oszlopos táblázatot kitöltöttük fullosra, a c-edik oszlopba pedig átcsorog r2>0 elem). Szerk. sajnos ez nem feltétlenül jó; r2 lehet nagyobb, mint q2, és akkor az utolsó oszlopot a maradékkal túltöltjük :(
Egyébként: - Készen vagyunk, teljes táblázattal, de csak (c-1) oszlopunk lett, és q2 sorral.
Az (n=102, c=7 --> q=14, r=4) példa arra, hogy a 2. lépés megoldja (az utolsó oszlop elemeinek száma (q+1) - (c - r) = 15-3 = 12), de a 3. és 4. lépések (amelyeket nem érünk el) rossz megoldást adnának (q2=17, r2=0).
Az (n=22, c=7 --> q=3, r=1) példa arra, hogy a 2. lépés nem oldja meg (a sorok számának 1-gyel növelése után az utolsó oszlopban (q+1) - (c - r) = 4-6 = (-2) elem lenne), de a 3. lépés megoldja (az oszlopok számát 1-gyel csökkentve q2=3 sor adódik c-1=6 oszlopban, és az utolsó (7.) oszlopba átcsorog r2=4 elem). Szerk. bocsánat, ez bugos -- az r2=4 elem nem fér el a 7. oszlopban, mivel csak q2=3 sorunk van!
Az (n=12, c=7 --> q=1, r=5) példa arra, hogy a 4. lépés oldja meg. A 2. lépés (negatív maradékos módszer, sorok számának növelése) q+1=2 sorral dolgozna, de a 7. oszlopba (q+1) - (c - r) = 2-2 = 0 elemet helyezne, így a 7. oszlop eltűnik. A 3. lépés (pozitív maradékos módszer, oszlopok számának csökkentése) c-1=6 oszloppal dolgozik, így q2=2 sorunk lesz, viszont r2=0 elem folyik át a 7. oszlopba, így az 7. oszlop itt is eltűnik, és azért eljutunk a 4. lépéshez -- csak 6 oszloppal lehet megoldani.
Később megpróbálok írni ide egy példa implementációt C-ben (már csak a magam kedvére is).
- A hozzászóláshoz be kell jelentkezni
Ilyen eset
(c-1)(c-2)/2
van [...], a legnagyobb azA=c-2, B=1, n=(c-1)^2
Továbbmorfondíroztam ezen -- ez a módszer nemcsak jó, hanem nagyszerű :) Ugyanis ha az első (n, c) inputra r<=0 jön ki (vagyis az utolsó oszlop kiürül), akkor tudsz elégséges követelményt megfogalmazni a c-re úgy, hogy második nekifutásra a módszer biztosan működjön: (√n)+1>c. Be tudsz állítani egy olyan új c-t, amire a módszer működni fog.
- Ha n négyzetszám, akkor √n egész, így c := √n megfelel.
- Ha n nem négyzetszám, akkor c := (⌊√n⌋+1) a legszorosabban értelmezett jó érték. (Lássuk azt, hogy ha n négyzetszám, akkor ez a számítás nem felel meg c-hez!)
A fentieket együttesen úgy is kifejezhetjük, hogy c :=⌈√n⌉.
Itt az az érdekes, hogy C-ben hogyan kódolod ezt le. Nekem az egyesített, felső egészrészes forma (c := ⌈√n⌉) nem tetszik, mert a c-r felső korlát van, tehát ha a ceil(sqrt(n))-ben mind az sqrt, mint a ceil felfelé kerekít, abból baj lehet. (Pl. n négyzetszám, de sqrt(n) egy olyan lebegőpontos értéket ad, ami a matematikai, egész értékű négyzetgyöknél epszilonnal nagyobb, amit aztán a ceil felkerekít a következő egészre.) Úgyhogy a szétválasztott esetek jobban tetszenek. Ott viszont:
Egyrészt hogyan tudjuk biztonsággal (egzaktul) megnézni, hogy n négyzetszám-e?
Másrészt sqrt()-hez a lebegőpontos környezetet úgy kell beállítani, hogy nulla (vagy mínusz végtelen) felé kerekítsen, attól függetlenül, hogy utána az eredményre a floor()-t alkalmaznánk. (Elvileg nem tartom lehetetlennek, hogy alapból felfelé kerekítő floating point env-nél az sqrt(n) egész számot adna olyan n-re, amely n=(k^2)-1 valamely egész k-ra. És akkor a floor(sqrt(n)) eggyel nagyobb értéket adna (nevesül floor(k)==k-t), mint a matematikai ⌊√n⌋ (ami k-1 lenne), vagyis a "c=floor(sqrt(n))+1" értékadás megszegné a c-re vonatkozó követelményt.)
Őszintén szólva nincs jobb ötletem, mint valahol feltúrni egy integer sqrt módszert (vagy "szegényemberes" megoldással megcsinálni lineáris vagy logaritmikus kereséssel), amely pont az ⌊√n⌋ értéket találja meg, utána pedig visszafelé ellenőrizni (egész aritmetikával), hogy ⌊√n⌋*⌊√n⌋ == n. Ha igen, akkor n négyzetszám (és c:=⌊√n⌋=√n), egyébként c nem négyzetszám (és c:=⌊√n⌋+1).
- A hozzászóláshoz be kell jelentkezni
Ilyesmit lehetne:
if (n<2) {
c= 1;
} else {
for (found=0; !found; --c) {
q= (n+c-1)/c;
r= n - q*(c-1);
found= (r>0);
}
}
- A hozzászóláshoz be kell jelentkezni
Ha emberi sorrendben írod ki (balról jobbra), akkor látszik, hogy miért nincs megoldás, mert több hasáb lesz hiányos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- A hozzászóláshoz be kell jelentkezni
De akkor meg csak hat oszlopom van.
Ez nem igaz, a feladat sehol nem kötötte ki, hogy egy oszlopban minimum 1 tételnek kell lennie. Nem is kötheti ki, mert ha N az osztó akkor a maradék 0 és N-1 közé kell, hogy essen. Vagyis továbbra is 7 hasáb van, csak az utolsó hasáb, vagyis a maradék 0 tételt tartalmaz.
- A hozzászóláshoz be kell jelentkezni
Hát matematikailag igen. Viszont tipográfiailag nézve kicsit ügyetlenül nézne ki, ha üres hasábok lennének az újságban.
- A hozzászóláshoz be kell jelentkezni
ilyen gyakorlatiasan nézve tehát a hasábok szélességével is operálnod kell
- A hozzászóláshoz be kell jelentkezni
Oké, akkor mit kell érteni az alatt, hogy az első c-1 hasáb tele legyen? Én úgy értelmeztem, hogy a sorok száma maximális, vagyis r=intsub(n/(c-1)), ebben a példádban r=intsub(102/(7-1))=17, a maradék 102%(7-1)=0. Gondolom ha van intsup akkor van intsub is.
Ha csak annyit jelent, hogy egyenlő számú elem van bennük, akkor át lehet vinni valamennyi tételt az utolsó oszlopba, ha intsub(n/(c-1))-n%(c-1)>=c. Ha n<c akkor mindenképp lesznek üres oszlopok. A kettő között valamiből engedni kell, pl. n=36, c=7-nél mi lenne a jó megoldás?
- A hozzászóláshoz be kell jelentkezni
n=36, c=7-nél mi lenne a jó megoldás
Ez egy jó példa. Ha oszloponként 5 elemmel dolgozunk, akkor nem férünk bele 7 oszlopba (5*7=35 < 36); ha pedig 6 elemmel, akkor az utolsó oszlop kiürül (6*6=36).
Ha megnézed NevemTeve hozzászólását itt, akkor az n=36, c=7 számpár pont az az eset, amikor az adott c-hez az n a legnagyobb olyan érték, aminél kiürül az utolsó oszlop (amikor a sorok számát felfelé kerekítjük): n=(c-1)^2; 36=(7-1)^2.
A megoldás szerintem az, hogy -- mivel n sokkal inkább rögzítettnek tűnik, mint c -- a c értékét kell csökkenteni; kevesebb oszlop kell. Tömören: c :=⌈√n⌉; de ezt C-ben egzaktul kódolni macerás (ld. a linkelt kommentemet).
- A hozzászóláshoz be kell jelentkezni
Támadt egy új ötletem! :) (Bocsánat, ha valaki már írta a topicban.)
A táblázatban a helyeket (cellákat) töltsük fel sorfolytonosan, majd a megtalált cellákat az értékekkel töltsük fel oszlopfolytonosan!
Ennek az a szépsége, hogy tetszőleges (n>0, c>0) párra működik, és a kimenet jól néz ki, mert az összes oszlop majdnem ugyanolyan magas.
Ennek a "majdnem ugyanolyannak" itt a formális meghatározása (példa: n=27, c=5):
0 1 2 3 4
0 X X X X X
1 X X X X X
2 X X X X X
3 X X X X X
4 X X X X X
5 X X
n = q * c + r (q >= 0; c > r >= 0)
A q megadja a teli sorok számát, az r pedig megadja, hogy az utolsó, nem teli sorban hány maradék elem van. Ha r=0, akkor egy szép teli téglalapot kaptunk.
Ha pedig r>0, akkor mindig az az elrendezés, a sorfolytonos cellaválasztás következtében, hogy a bal oldalon található egy r oszlopból és q+1 sorból álló "A" téglalap, a jobb oldalon pedig egy c-r oszlopból és q sorból álló "B" téglalap:
0 1 2 3 4
0 A A B B B
1 A A B B B
2 A A B B B
3 A A B B B
4 A A B B B
5 A A
Aritmetikailag felírva a cellák számát az A és B téglalapokban:
r*(q+1) + (c-r)*q = r*q + r + c*q - r*q = c*q + r = n
Tehát jól számoltunk, valóban az n db cellát helyeztük el.
Ennek a felírásnak további szépsége az, hogy független attól, hogy r=0 vagy r>0. Ha ui. történetesen r=0, akkor az A téglalap szélessége egyszerűen 0 oszlop, a B téglalap szélessége pedig c-r = c-0 = c oszlop.
Akkor a cellákat elhelyeztük; hogyan töltsük fel azokat? Ugyanis printelni sorfolytonosan tudunk. Nem nehéz; minden sorban az induló érték (a 0. oszlop értéke) magának a sornak a száma. Ahogy jobbra haladunk az adott sorban, az értéket annyival kell megnövelnünk, mint az éppen elhagyandó oszlop magassága. Ha a jelenlegi oszlop száma (nullával kezdve a számozást) kisebb mint r, akkor ez a növekmény (vagyis az oszlop magassága) q+1, egyébként pedig q.
(Itt is látszik, hogy ha r=0, vagyis az osztás egzakt, akkor az "oszlop száma kisebb mint r" sosem teljesül, vagyis a növekmény mindig q.)
Itt a program:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#define CELL_WIDTH 3
static int
get_positive_long(long *val, const char *str)
{
long tmp;
char *end;
errno = 0;
tmp = strtol(str, &end, 0);
if (end == str || *end != '\0' || errno != 0 || tmp <= 0) {
(void)fprintf(stderr, "invalid value: \"%s\"\n", str);
return -1;
}
*val = tmp;
return 0;
}
int
main(int argc, char **argv)
{
long num_val, num_col;
ldiv_t qr;
long row, col, val, i;
if (argc != 3) {
(void)fprintf(stderr, "usage: %s num_val num_col\n", argv[0]);
return EXIT_FAILURE;
}
if (get_positive_long(&num_val, argv[1]) == -1 ||
get_positive_long(&num_col, argv[2]) == -1) {
return EXIT_FAILURE;
}
if (num_val < num_col) {
(void)fprintf(stderr, "expected num_val(%ld) >= num_col(%ld)\n", num_val,
num_col);
return EXIT_FAILURE;
}
qr = ldiv(num_val, num_col);
row = col = val = i = 0;
for (;;) {
(void)printf("%*ld", CELL_WIDTH + (col > 0), val);
if (i == num_val - 1) {
(void)printf("\n");
break;
}
if (col < num_col - 1) {
val += qr.quot + (col < qr.rem);
++col;
} else {
(void)printf("\n");
val = ++row;
col = 0;
}
++i;
}
return EXIT_SUCCESS;
}
... Ja, tényleg, joco01 már említette a sorfolytonosságot.
- A hozzászóláshoz be kell jelentkezni
> Támadt egy új ötletem!
Annyira nem lehet új, ha két napja én is ezt írtam :)
- A hozzászóláshoz be kell jelentkezni
#include <stdio.h>
#include <stdlib.h>
void draw(int num, int col, int row)
{
int i, j, n;
printf(" |");
for (j = 0; j < col; ++j) printf("#%-3i|", j+1);
printf("\n");
for (i = 0; i < row; ++i)
{
printf("#%-3i|", i+1);
for (j = 0, n = i; j < col; ++j, n += row)
(n < num) ? printf("%4i|", n) : printf(" -|");
printf("\n");
}
}
void calc(int num, int inp_col, int *out_col, int *row)
{
int m;
*out_col = inp_col;
m = num % inp_col;
*row = num / inp_col;
if (m == 0) return;
(*row)++;
if (inp_col - m < *row) return;
*out_col = num / *row;
if (num % *row > 0) (*out_col)++;
}
int main(int argc, char *argv[])
{
int an,ac,r,c;
an = atoi(argv[1]);
ac = atoi(argv[2]);
calc(an, ac, &c, &r);
if (ac != c) printf("Nem oldhato meg %i oszlopban\n", ac);
printf("Megoldhato %i oszlopban, %i sor\n", c, r);
draw(an, c, r);
return 0;
}
- A hozzászóláshoz be kell jelentkezni
Ez nagyon jónak látszik, az a matek benne, hogy c' = intsup(n/intsup(n/c))
, hogy pl.
n=37,c=7 esetén c'=intsup(37/intsup(37/7))=intsup(37/6)=7
n=36,c=7 esetén c'=intsup(36/intsup(36/7))=intsup(36/6)=6
- A hozzászóláshoz be kell jelentkezni