Hello,

I've passed successfully passed both tests 3N+1 and 101 Blocks.

3N+1 is similar to VIncent's solution.

101 Blocks solution is attached here. Mode ObjFPC is accepted which means we can use our modern pascal dialects. I was afraid it wouldn't be possible.

Thanks.

Thierry

Vincent Snijders wrote:
Thierry Coq schreef:
Thank you guys,
Has somebody here delivered a successful pascal program to the UVa online judge: http://icpcres.ecs.baylor.edu/onlinejudge/index.php ?

Test problem 100: http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=36

I just succesfully submitted and passed this test problem. See attachment for source code.

Vincent
------------------------------------------------------------------------

_______________________________________________
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

//==============================================================================
program test101_16_asobj(input, output);
//==============================================================================
// Submission n° 7034612
// result is right answer. Speed is OK: 0.000 s

{$MODE OBJFPC}
uses
  SysUtils;

type
  TBlock = class
    number: integer;
    stack: integer;
    above: TBlock; //the one higher on the pile. nil if nobody after
    below: TBlock; //the one below on the pile, nil if nobody before
  public
    procedure RemoveStackFromStack;
    procedure ResetBlocksAbove;
    procedure PutStackOnStack(aStack:integer);
  end;

const
  MaxBlocks = 25;
var
  WaitingForCommands: Boolean;
  aCommand: String;
  N : Integer; // blocksize
  table: array[0..MaxBlocks] of TBlock;
  tablelast: array[0..MaxBlocks] of TBlock;
  blocks: array[0..MaxBlocks] of TBlock;


//==============================================================================
//creates a block for each position on the table
procedure InitializeState;
//==============================================================================
var
  iBlock: integer;
  ablock: TBlock;
begin
  for iBlock := 0 to MaxBlocks do
  begin
    aBlock := TBlock.Create;
    aBlock.number := iBlock;
    aBlock.stack := iBlock;
    aBlock.above := nil;
    aBlock.below := nil;
    blocks[iBlock] := aBlock;
    table[iBlock] := aBlock;
    tableLast[iBlock] := aBlock;
  end;
end;


//==============================================================================
//prints the status of the table
procedure PrintState;
//==============================================================================
var
  iStack: integer;
  aBlock: TBlock;
begin
  for iStack := 0 to N-1 do
  begin
    write(iStack,':');
    aBlock := table[iStack];
    while (aBlock<>nil) do
    begin
      write(' ', aBlock.number);
      aBlock := aBlock.above;
    end;
    writeln;
  end;
end;

//==============================================================================
function IsIllegalMove(block1, block2: integer): Boolean;
//==============================================================================
begin
  //a move is illegal, if block1 = block2, or
  // if block1 and block2 are in the same pile...
  IsIllegalMove := false;

  // a = b
  if block1=block2 then
  begin
    IsIllegalMove := true;
  end
  else
  begin

    // a and b in same stack
    if (block1>=N) or (block2>=N) then
    begin
      IsIllegalMove := true;
    end
    else
    begin
      if blocks[block1].stack = blocks[block2].stack then
        IsIllegalMove := true;
    end;
  end;
end;


//==============================================================================
// removes the stack starting with aBlock from the current stack.
procedure TBlock.RemoveStackFromStack;
//==============================================================================
var
  oldStack : integer;
  previous : TBlock;
begin
  //removing the block from the current stack...
  oldStack := Self.stack;

  //unchaining the block;
  previous := Self.below;

  // reknitting forward chain
  if previous = nil then
    table[oldStack] := nil
  else
    previous.above := nil;

  //reknitting backwards chain
  Self.below := nil;
  tableLast[oldStack] := previous;
end;


//==============================================================================
// puts the block on top of the stack..
procedure TBlock.PutStackOnStack(aStack:integer);
//==============================================================================
var
  lastBlock: TBlock;
  nextBlock: TBlock;
begin

  if aStack<0 then exit;

  lastBlock := tableLast[ aStack];

  Self.RemoveStackFromStack;

  // don't add the block if it is already on the stack
  if assigned(lastBlock) then
    if lastBlock.Number = Self.Number then
      exit;

  //knitting forward chain...
  if not assigned(lastBlock) then
    table[aStack] := Self
  else
    lastBlock.above := Self;

  nextBlock := Self;
  while (nextBlock<>nil) do
  begin
    nextBlock.stack := aStack;
    tableLast[aStack] := nextBlock;
    nextBlock := nextBlock.above;
  end;

  //knitting backwards chain...
  if not assigned(lastblock) then
    Self.below := nil
  else
    Self.below := lastBlock;
end;


//==============================================================================
// moves all blocks above and including aBlock to their original stack
procedure TBlock.ResetBlocksAbove;
//==============================================================================
var
  firstBlock: TBlock;
  nextBlock: TBlock;
  aStack: integer;
begin

  // we need to move from the top block down... or we lose the stack 
information.
  aStack := Self.stack;

  firstBlock := tableLast[aStack];
  while (firstBlock<>nil) do
  begin
    if firstblock.number=Self.number then break;
    nextBlock := firstBlock.below;
    firstBlock.PutStackOnStack(firstBlock.number);
    firstBlock := nextBlock;
  end;
end;


//==============================================================================
procedure MoveOnto(block1, block2:integer);
//==============================================================================
begin
  blocks[block1].ResetBlocksAbove;
  blocks[block2].ResetBlocksAbove;
  blocks[block1].PutStackOnStack( blocks[block2].stack);
end;

//==============================================================================
procedure MoveOver(block1, block2:integer);
//==============================================================================
begin
  blocks[block1].ResetBlocksAbove;
  blocks[block1].PutStackOnStack( blocks[block2].stack);
end;

//==============================================================================
procedure PileOnto(block1, block2:integer);
//==============================================================================
begin
  blocks[block2].ResetBlocksAbove;
  blocks[block1].PutStackOnStack( blocks[block2].stack);
end;

//==============================================================================
procedure PileOver(block1, block2:integer);
//==============================================================================
begin
  blocks[block1].PutStackOnStack( blocks[block2].stack);
end;

//==============================================================================
//processes each command
procedure ProcessCommand(const aCommand:String);
//==============================================================================
var
  C1, C2: Char;
  B1, B2 : String;
  p : integer;   // position
  dec: integer;
  aChar : char;
  l : integer;
  block1, block2 : integer;
begin

  // my parsing has to be faster.
  // each command is of the format : command1 block1 command2 block2, like:
  // "move a onto b"
  // "move a over b"
  // "pile a onto b"
  // "pile a over b"
  // C1 B1 C2 B2
  // except "quit"

  // parse command
  //writeln('p:', p); //DEBUG
  // checking for the quit command
  if (aCommand[1] = 'q') then //'quit'
  begin
    WaitingForCommands := false;
    Exit;
  end;

  // reinit for parsing command:
  dec := 0;
  l := length(aCommand);

  // getting C1
  C1 := aCommand[1]; // C1 is always 4 letters, only the first is needed

  // getting B1's position
  p := 6;
  B1 := aCommand[p];
  inc(p);
  aChar := aCommand[p];
  if aChar <>' ' then
  begin
    inc(dec); // the B1 is on two chars...
    B1 := B1 + aChar;
  end;
  block1 := StrToInt(B1);


  C2 := aCommand[9+dec];  // C2 is always 4 letters, only the second is needed

  p := 13+dec;

  B2 := aCommand[p];
  if p<l then
  begin
    inc(p);
    aChar := aCommand[p];
    if aChar <>' ' then
    begin
      B2 := B2 + aChar;
    end;
  end;
  block2 := StrToInt(B2);


  If not isIllegalMove(block1, block2) then
  begin
    if C1 = 'm' then //move
    begin
      if C2 = 'n' then //onto
        MoveOnto(block1, block2)
      else
        MoveOver(block1, block2);
    end
    else
    begin
      if C2 = 'n' then
        PileOnto(block1, block2)
      else
        PileOver(block1, block2);
    end;
  end;
end;

// main program read data
begin
  Readln(N);
  InitializeState;
  WaitingForCommands := true;

  while WaitingForCommands do
  begin
    Readln( aCommand);
    ProcessCommand( aCommand);
  end;

  PrintState;
end.

_______________________________________________
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to