16

I just finished participating in the 2009 ACM ICPC Programming Conest in the Latinamerican Finals. These questions were for Brazil, Bolivia, Chile, etc.

My team and I could only finish two questions out of the eleven (not bad I think for the first try).

Here's one we could finish. I'm curious to seeing any variations to the code. The question in full: ps: These questions can also be found on the official ICPC website available to everyone.


In the land of ACM ruled a greeat king who became obsessed with order. The kingdom had a rectangular form, and the king divided the territory into a grid of small rectangular counties. Before dying the king distributed the counties among his sons.

The king was unaware of the rivalries between his sons: The first heir hated the second but not the rest, the second hated the third but not the rest, and so on...Finally, the last heir hated the first heir, but not the other heirs.

As soon as the king died, the strange rivaly among the King's sons sparked off a generalized war in the kingdom. Attacks only took place between pairs of adjacent counties (adjacent counties are those that share one vertical or horizontal border). A county X attacked an adjacent county Y whenever X hated Y. The attacked county was always conquered. All attacks where carried out simultanously and a set of simultanous attacks was called a battle. After a certain number of battles, the surviving sons made a truce and never battled again.

For example if the king had three sons, named 0, 1 and 2, the figure below shows what happens in the first battle for a given initial land distribution:

alt text


INPUT

The input contains several test cases. The first line of a test case contains four integers, N, R, C and K.

  1. N - The number of heirs (2 <= N <= 100)
  2. R and C - The dimensions of the land. (2 <= R,C <= 100)
  3. K - Number of battles that are going to take place. (1 <= K <= 100)

Heirs are identified by sequential integers starting from zero. Each of the next R lines contains C integers HeirIdentificationNumber (saying what heir owns this land) separated by single spaces. This is to layout the initial land.

The last test case is a line separated by four zeroes separated by single spaces. (To exit the program so to speak)


Output

For each test case your program must print R lines with C integers each, separated by single spaces in the same format as the input, representing the land distribution after all battles.


Sample Input:                          Sample Output:
3 4 4 3                                2 2 2 0
0 1 2 0                                2 1 0 1 
1 0 2 0                                2 2 2 0
0 1 2 0                                0 2 0 0 
0 1 2 2

Another example:

Sample Input:                          Sample Output:
4 2 3 4                                1 0 3
1 0 3                                  2 1 2
2 1 2
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Sergio Tapia
  • 40,006
  • 76
  • 183
  • 254
  • 3
    Why the vote to close? Is this offensive to you? – Sergio Tapia Oct 25 '09 at 17:35
  • The question is copied verbatum. Nobody "wins" a battle. You're just supposed to print out the finial layout after "K" battles. – Sergio Tapia Oct 25 '09 at 17:38
  • 6
    I cannot understand why stackoverflowers fuss over whether code-golf questions are legit or not. I suggest to leave this question open for members of the community to solve. The resulting solutions can be quite educational for people like me. Nothing showcases the ability of programming languages more succinctly than code golf... – Zaid Oct 25 '09 at 17:43
  • Your second diagram (Attacks for the first battle) seems lacking in attack points. – Tordek Oct 25 '09 at 17:53
  • At least give the guy a chance to fix the mistakes in his problem, if there are any left... – Zaid Oct 25 '09 at 17:54
  • 4
    I'm really shocked to so much negativity from the high-nosed users. FFS, it's a question for anyone who wants to give it a shot. Like I said, we solved it in Java and I'd like to see other solutions. Should I rebrand the question as Code-Volleyball so people don't feel the CODE-Golf name was stolen? Grow up. – Sergio Tapia Oct 25 '09 at 18:16
  • 43
    Every time a code golf question is posted I see people complaining and I wonder: "Is it really that difficult to add 'code-golf' to your list of ignored tags?" – Steve Losh Oct 25 '09 at 18:54
  • @Steve Losh - the problem is questions get closed much easier than they get reopened (and of course, they "suffer" loss of interest, while they are closed). What we need is vote to close/vote to not close - voting system. – Rook Oct 26 '09 at 04:50
  • Actually, the above comment has nothing to do with you. I was thinking of something else when I started writing it, and then wrote this, but forgot to remove your name :( – Rook Oct 26 '09 at 04:51
  • 2
    Meta discussion on the appropriateness of code-golf on SO: http://meta.stackexchange.com/questions/20912/ (so far the ruling is yes) and on what makes a "good" code-golf question: http://meta.stackexchange.com/questions/24242/acceptable-level-of-code-golf-questions (this on could probably use more input...). Since the later we have seen a mixture of code-gold questions closed and left open, so YMMV. – dmckee --- ex-moderator kitten Oct 26 '09 at 10:48

6 Answers6

5

Perl, 233 char

{$_=<>;($~,$R,$C,$K)=split;if($~){@A=map{$_=<>;split}1..$R;$x=0,
@A=map{$r=0;for$d(-$C,$C,1,-1){$r|=($y=$x+$d)>=0&$y<@A&1==($_-$A[$y])%$~
if($p=(1+$x)%$C)>1||1-$d-2*$p}$x++;($_-$r)%$~}@A
while$K--;print"@a\n"while@a=splice@A,0,$C;redo}}

The map is held in a one-dimensional array. This is less elegant than the two-dimensional solution, but it is also shorter. Contains the idiom @A=map{...}@A where all the fighting goes on inside the braces.

mob
  • 117,087
  • 18
  • 149
  • 283
2

Python (420 characters)

I haven't played with code golf puzzles in a while, so I'm sure I missed a few things:

import sys
H,R,C,B=map(int,raw_input().split())
M=(1,0), (0,1),(-1, 0),(0,-1)
l=[map(int,r.split())for r in sys.stdin]
n=[r[:]for r in l[:]]
def D(r,c):
 x=l[r][c]
 a=[l[r+mr][c+mc]for mr,mc in M if 0<=r+mr<R and 0<=c+mc<C]
 if x==0and H-1in a:n[r][c]=H-1
 elif x-1in a:n[r][c]=x-1
 else:n[r][c]=x
G=range
for i in G(B):
 for r in G(R):
  for c in G(C):D(r,c)
 l=[r[:] for r in n[:]]
for r in l:print' '.join(map(str,r))
Steve Losh
  • 19,642
  • 2
  • 51
  • 44
  • When I execute this, the code also outputs the NRCK-values, starting from the second test case (So, `4 2 3 4` and `0 0 0 0`). – Stephan202 Oct 25 '09 at 20:51
  • **@Stephan202:** It definitely doesn't do that for me... I don't see how it could happen, reading the code. – Steve Losh Oct 25 '09 at 22:54
  • @Steve: I'm feeding the input as specified in Brian's post. I run the code as `python2.6 steve.py < input`. The output should then consist of 6 lines (again, see Brian's post). For some reason the output is 8 lines, however. Very odd that you do not observe the same behavior... – Stephan202 Oct 25 '09 at 23:45
  • @Steve: I had a look at your code. It only handles *one* test case, not all of them. – Stephan202 Oct 26 '09 at 00:17
  • Ah, ok, I see now -- I didn't read the original closely enough and figured it was one test case per run. This solution just takes one test case at a time. – Steve Losh Oct 26 '09 at 00:58
  • @Steve: I just updated my answer with a Python version. I borrowed some of your ideas :) – Stephan202 Oct 26 '09 at 01:07
2

Lua, 291 Characters

g=loadstring("return io.read('*n')")repeat n=g()r=g()c=g()k=g()l={}c=c+1 for
i=0,k do w={}for x=1,r*c do a=l[x]and(l[x]+n-1)%n w[x]=i==0 and x%c~=0 and
g()or(l[x-1]==a or l[x+1]==a or l[x+c]==a or l[x-c]==a)and a or
l[x]io.write(i~=k and""or x%c==0 and"\n"or w[x].." ")end l=w end until n==0
gwell
  • 2,695
  • 20
  • 20
1

F#, 675 chars

let R()=System.Console.ReadLine().Split([|' '|])|>Array.map int
let B(a:int[][]) r c g=
 let n=Array.init r (fun i->Array.copy a.[i])
 for i in 1..r-2 do for j in 1..c-2 do
  let e=a.[i].[j]-1
  let e=if -1=e then g else e
  if a.[i-1].[j]=e||a.[i+1].[j]=e||a.[i].[j-1]=e||a.[i].[j+1]=e then
   n.[i].[j]<-e
 n
let mutable n,r,c,k=0,0,0,0
while(n,r,c,k)<>(0,2,2,0)do
 let i=R()
 n<-i.[0]
 r<-i.[1]+2
 c<-i.[2]+2
 k<-i.[3]
 let mutable a=Array.init r (fun i->
 if i=0||i=r-1 then Array.create c -2 else[|yield -2;yield!R();yield -2|])
 for j in 1..k do a<-B a r c (n-1)
 for i in 1..r-2 do
  for j in 1..c-2 do
   printf "%d" a.[i].[j]
  printfn ""

Make the array big enough to put an extra border of "-2" around the outside - this way can look left/up/right/down without worrying about out-of-bounds exceptions.

B() is the battle function; it clones the array-of-arrays and computes the next layout. For each square, see if up/down/left/right is the guy who hates you (enemy 'e'), if so, he takes you over.

The main while loop just reads input, runs k iterations of battle, and prints output as per the spec.

Input:

3 4 4 3
0 1 2 0
1 0 2 0
0 1 2 0
0 1 2 2
4 2 3 4
1 0 3
2 1 2
0 0 0 0

Output:

2220
2101
2220
0200
103
212
Brian
  • 117,631
  • 17
  • 236
  • 300
1

Python 2.6, 383 376 Characters

This code is inspired by Steve Losh' answer:

import sys
A=range
l=lambda:map(int,raw_input().split())
def x(N,R,C,K):
 if not N:return
 m=[l()for _ in A(R)];n=[r[:]for r in m]
 def u(r,c):z=m[r][c];n[r][c]=(z-((z-1)%N in[m[r+s][c+d]for s,d in(-1,0),(1,0),(0,-1),(0,1)if 0<=r+s<R and 0<=c+d<C]))%N
 for i in A(K):[u(r,c)for r in A(R)for c in A(C)];m=[r[:]for r in n]
 for r in m:print' '.join(map(str,r))
 x(*l())
x(*l())

Haskell (GHC 6.8.2), 570 446 415 413 388 Characters

Minimized:

import Monad
import Array
import List
f=map
d=getLine>>=return.f read.words
h m k=k//(f(\(a@(i,j),e)->(a,maybe e id(find(==mod(e-1)m)$f(k!)$filter(inRange$bounds k)[(i-1,j),(i+1,j),(i,j-1),(i,j+1)])))$assocs k)
main=do[n,r,c,k]<-d;when(n>0)$do g<-mapM(const d)[1..r];mapM_(\i->putStrLn$unwords$take c$drop(i*c)$f show$elems$(iterate(h n)$listArray((1,1),(r,c))$concat g)!!k)[0..r-1];main

The code above is based on the (hopefully readable) version below. Perhaps the most significant difference with sth's answer is that this code uses Data.Array.IArray instead of nested lists.

import Control.Monad
import Data.Array.IArray
import Data.List

type Index = (Int, Int)
type Heir = Int
type Kingdom = Array Index Heir

-- Given the dimensions of a kingdom and a county, return its neighbors.
neighbors :: (Index, Index) -> Index -> [Index]
neighbors dim (i, j) =
  filter (inRange dim) [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]

-- Given the first non-Heir and a Kingdom, calculate the next iteration.
iter :: Heir -> Kingdom -> Kingdom
iter m k = k // (
  map (\(i, e) -> (i, maybe e id (find (== mod (e - 1) m) $
                                    map (k !) $ neighbors (bounds k) i))) $
  assocs k)

-- Read a line integers from stdin.
readLine :: IO [Int]
readLine = getLine >>= return . map read . words

-- Print the given kingdom, assuming the specified number of rows and columns.
printKingdom :: Int -> Int -> Kingdom -> IO ()
printKingdom r c k =
  mapM_ (\i -> putStrLn $ unwords $ take c $ drop (i * c) $ map show $ elems k)
        [0..r-1]

main :: IO ()
main = do
  [n, r, c, k] <- readLine     -- read number of heirs, rows, columns and iters
  when (n > 0) $ do                -- observe that 0 heirs implies [0, 0, 0, 0]
    g <- sequence $ replicate r readLine   -- read initial state of the kingdom
    printKingdom r c $                      -- print kingdom after k iterations
      (iterate (iter n) $ listArray ((1, 1), (r, c)) $ concat g) !! k
    main                                               -- handle next test case
Community
  • 1
  • 1
Stephan202
  • 59,965
  • 13
  • 127
  • 133
  • @Stephan202, if you split the Python and Haskell into 2 separate answers, this will allow people to vote for them separately. – system PAUSE Oct 26 '09 at 15:46
1

AWK - 245

A bit late, but nonetheless... Data in a 1-D array. Using a 2-D array the solution is about 30 chars longer.

NR<2{N=$1;R=$2;C=$3;K=$4;M=0}NR>1{for(i=0;i++<NF;)X[M++]=$i}END{for(k=0;k++<K;){
for(i=0;i<M;){Y[i++]=X[i-(i%C>0)]-(b=(N-1+X[i])%N)&&X[i+((i+1)%C>0)]-b&&X[i-C]-b
&&[i+C]-b?X[i]:b}for(i in Y)X[i]=Y[i]}for(i=0;i<M;)printf"%s%d",i%C?" ":"\n",
X[i++]}
Dan Andreatta
  • 3,611
  • 1
  • 22
  • 15