A programozó munkája a legkönnyebb /2

De tényleg, pl. ennél mi egyszerűbb: írjunk ki n tételt c hasábban, úgy, hogy az első c-1 hasáb tele legyen, az utolsóban legyen a maradék. Ehhez tényleg nem kell más, csak az alsó és felső egészrész, és/vagy a maradékos osztás ismerete.

Akkor most fussunk neki az n=18, c=7 vagy n=18, c=8 esetnek.

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 -- -- -- -- -- --

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?

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.

Szerkesztve: 2024. 11. 20., sze – 10:57

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.

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):

  1. 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).
     

  2. 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.

> 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`

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:

  1. 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).
     

  2. 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).

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

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

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):

  1. 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:
  2. 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:
  3. 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:
  4. 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).

Ilyen eset (c-1)(c-2)/2 van [...], a legnagyobb az A=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).

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
Szerkesztve: 2024. 11. 20., sze – 05:10

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.

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?

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).

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.

#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;
}