comp.lang.ada
 help / color / mirror / Atom feed
* advent of code day 11
@ 2020-12-11 17:07 Stephen Leake
  2020-12-11 18:24 ` John Perry
  0 siblings, 1 reply; 10+ messages in thread
From: Stephen Leake @ 2020-12-11 17:07 UTC (permalink / raw)


mildly interesting; variation on Conway's Game of Life.
-- 
-- Stephe

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 17:07 advent of code day 11 Stephen Leake
@ 2020-12-11 18:24 ` John Perry
  2020-12-11 19:07   ` Jeffrey R. Carter
                     ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: John Perry @ 2020-12-11 18:24 UTC (permalink / raw)


On Friday, December 11, 2020 at 11:08:00 AM UTC-6, Stephen Leake wrote:
> mildly interesting; variation on Conway's Game of Life. 

I recognized that, too. A solution should not be hard to parallelize, and I'd like to, but for now I have other tasks. (no pun intended, well, OK yes it was)

Here's a couple of questions for the Ada experts. For each round I used two charts, a source and a result. These are arrays, defined like so:

   type Status is ( Floor, Empty, Occupied );

   type Chart_Array is array( Positive range <> , Positive range <> ) of Status;

   Chart1, Chart2: Chart_Array; -- actually defined with appropriate dimensions

A procedure named `Iterate_Seating` applies the given rules to a Chart_Array; an `if` statement determines which iterates into the other.

I thought it would be clearer to use references to switch from one chart to the other, but I had trouble doing that last night. Now I can get it this way:

   Source: Chart_Array renames Chart1;
   Result: Chart_Array renames Chart2;

   while Changed loop

      Perform_Round( Source => Source , Result => Result , ... );
      declare Tmp: Chart_Array renames Source;
      begin
         Source := Result;
         Result := Tmp;
      end;

   end loop;

Does this technique swap references, or does it copy the arrays element-by-element? The run times are the same even if I compel a copy operation; I suppose it's because the arrays aren't large enough, and there aren't enough copies, to make a difference.

thanks
john perry

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 18:24 ` John Perry
@ 2020-12-11 19:07   ` Jeffrey R. Carter
  2020-12-11 19:29   ` gautier...@hotmail.com
  2020-12-12 20:27   ` Stephen Leake
  2 siblings, 0 replies; 10+ messages in thread
From: Jeffrey R. Carter @ 2020-12-11 19:07 UTC (permalink / raw)


On 12/11/20 7:24 PM, John Perry wrote:
> 
>     Source: Chart_Array renames Chart1;
>     Result: Chart_Array renames Chart2;
> 
>     while Changed loop
> 
>        Perform_Round( Source => Source , Result => Result , ... );
>        declare Tmp: Chart_Array renames Source;
>        begin
>           Source := Result;
>           Result := Tmp;

Renaming simply creates an additional way to name something. This should be the 
same as

    Chart1 := Chart2;
    Chart2 := Chart1;

-- 
Jeff Carter
"[I]f we should ever separate, my little plum,
I want to give you one little bit of fatherly advice. ... Never
give a sucker an even break."
Poppy
97

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 18:24 ` John Perry
  2020-12-11 19:07   ` Jeffrey R. Carter
@ 2020-12-11 19:29   ` gautier...@hotmail.com
  2020-12-11 19:35     ` gautier...@hotmail.com
                       ` (2 more replies)
  2020-12-12 20:27   ` Stephen Leake
  2 siblings, 3 replies; 10+ messages in thread
From: gautier...@hotmail.com @ 2020-12-11 19:29 UTC (permalink / raw)


> Perform_Round( Source => Source , Result => Result , ... ); 
> declare Tmp: Chart_Array renames Source; 
> begin 
> Source := Result; 
> Result := Tmp; 
> end; 

To complete Jeff's answer, what you are doing is not a swap: it's equivalent to 
Source := Result;
Result := Source;
Ooops.
The ":=" makes a complete copy of the arrays.
So you'd need above "Tmp : Chart_Array := Source" to have a correct swap with 3 copies.
Of course it feels a bit heavy to make all those copies. And you understandably want to avoid playing with pointers. So a solution is to define:
Map : array (0 .. 1) of Chart_Array;
...
current := 0;
loop
  next := 1 - current;
  Perform_Round( Source => Map (current), Result => Map (next) , ... ); 
  current := next;
end loop;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 19:29   ` gautier...@hotmail.com
@ 2020-12-11 19:35     ` gautier...@hotmail.com
  2020-12-11 22:40     ` Jeffrey R. Carter
  2020-12-11 23:49     ` John Perry
  2 siblings, 0 replies; 10+ messages in thread
From: gautier...@hotmail.com @ 2020-12-11 19:35 UTC (permalink / raw)


Full example in 2 flavours:
https://github.com/zertovitch/hac/blob/master/exm/aoc/2020/aoc_2020_11_full_ada.adb (full Ada only)
https://github.com/zertovitch/hac/blob/master/exm/aoc/2020/aoc_2020_11.adb (HAC & full Ada)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 19:29   ` gautier...@hotmail.com
  2020-12-11 19:35     ` gautier...@hotmail.com
@ 2020-12-11 22:40     ` Jeffrey R. Carter
  2020-12-11 23:45       ` John Perry
  2020-12-11 23:49     ` John Perry
  2 siblings, 1 reply; 10+ messages in thread
From: Jeffrey R. Carter @ 2020-12-11 22:40 UTC (permalink / raw)


On 12/11/20 8:29 PM, gautier...@hotmail.com wrote:
> 
> So you'd need above "Tmp : Chart_Array := Source" to have a correct swap with 3 copies.
> Of course it feels a bit heavy to make all those copies. And you understandably want to avoid playing with pointers. So a solution is to define:
> Map : array (0 .. 1) of Chart_Array;
> ...
> current := 0;
> loop
>    next := 1 - current;
>    Perform_Round( Source => Map (current), Result => Map (next) , ... );
>    current := next;
> end loop;

I don't see a need for a swap, or to avoid copying. I did

Current : Floorplan := Read;
Future  : Floorplan := (others => (others => Floor) );
...
All_Rounds : loop
    for R in ... loop
       for S in ... loop
          if Current (R, S) /= Floor then -- It's a seat
             Future (R, S) :=
                Next_State (Current (R, S), Num_Occupied (Current, R, S) );
          end if; -- else Future (R, S) = Floor
       end loop;
    end loop;

    exit All_Rounds when Current = Future;

    Current := Future;
end loop All_Rounds;

which took 34 ms, well within the timing requirements for the problem.

-- 
Jeff Carter
"[I]f we should ever separate, my little plum,
I want to give you one little bit of fatherly advice. ... Never
give a sucker an even break."
Poppy
97

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 22:40     ` Jeffrey R. Carter
@ 2020-12-11 23:45       ` John Perry
  0 siblings, 0 replies; 10+ messages in thread
From: John Perry @ 2020-12-11 23:45 UTC (permalink / raw)


On Friday, December 11, 2020 at 4:40:51 PM UTC-6, Jeffrey R. Carter wrote:
> I don't see a need for a swap, or to avoid copying. I did 
> 
> Current : Floorplan := Read; 
> Future : Floorplan := (others => (others => Floor) ); 
> ... 
> 
> Current := Future; 
> end loop All_Rounds; 
> 
> which took 34 ms, well within the timing requirements for the problem.

I agree it's not needed in this case. I raised the question simply because I'd like to know how it could be done in cases where it might well be important to save the time. I've sometimes shaved significant percentages of running time off programs by doing nothing more than avoiding copying arrays.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 19:29   ` gautier...@hotmail.com
  2020-12-11 19:35     ` gautier...@hotmail.com
  2020-12-11 22:40     ` Jeffrey R. Carter
@ 2020-12-11 23:49     ` John Perry
  2020-12-12  9:38       ` Maxim Reznik
  2 siblings, 1 reply; 10+ messages in thread
From: John Perry @ 2020-12-11 23:49 UTC (permalink / raw)


On Friday, December 11, 2020 at 1:29:58 PM UTC-6, gautier...@hotmail.com wrote:
> The ":=" makes a complete copy of the arrays.

That's what I was afraid of. 

> Of course it feels a bit heavy to make all those copies. And you understandably want to avoid playing with pointers.

Exactly!

So a solution is to define: 
> Map : array (0 .. 1) of Chart_Array; 
> ... 
> current := 0; 
> loop 
> next := 1 - current; 
> Perform_Round( Source => Map (current), Result => Map (next) , ... ); 
> current := next; 
> end loop;

This is a nice alternative, thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 23:49     ` John Perry
@ 2020-12-12  9:38       ` Maxim Reznik
  0 siblings, 0 replies; 10+ messages in thread
From: Maxim Reznik @ 2020-12-12  9:38 UTC (permalink / raw)


Perhaps you might be interested in using generics for this solution

https://github.com/reznikmm/ada-howto/blob/advent-2020/md/11/11.md

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: advent of code day 11
  2020-12-11 18:24 ` John Perry
  2020-12-11 19:07   ` Jeffrey R. Carter
  2020-12-11 19:29   ` gautier...@hotmail.com
@ 2020-12-12 20:27   ` Stephen Leake
  2 siblings, 0 replies; 10+ messages in thread
From: Stephen Leake @ 2020-12-12 20:27 UTC (permalink / raw)


John Perry <john.perry@usm.edu> writes:

> On Friday, December 11, 2020 at 11:08:00 AM UTC-6, Stephen Leake wrote:
>> mildly interesting; variation on Conway's Game of Life. 
>
> I thought it would be clearer to use references to switch from one
> chart to the other, but I had trouble doing that last night. Now I can
> get it this way:
>
>    Source: Chart_Array renames Chart1;
>    Result: Chart_Array renames Chart2;

A 'renames' declaration creates a _static_ name for the object that is
the result of the expression; the expression is evaluated once when the
'renames' declaration is evaluated. When the name is used, it is the
same as any other object name.

>    while Changed loop
>
>       Perform_Round( Source => Source , Result => Result , ... );
>       declare Tmp: Chart_Array renames Source;

'Tmp' is evaluated each time around the loop, but since the global
Source is static, it always has the same value of Chart1.

>       begin Source := Result;

This does not revaluate the expression for global Source; it uses the
global Source name to determine where to store a copy of Result.

-- 
-- Stephe

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-12-12 20:27 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-11 17:07 advent of code day 11 Stephen Leake
2020-12-11 18:24 ` John Perry
2020-12-11 19:07   ` Jeffrey R. Carter
2020-12-11 19:29   ` gautier...@hotmail.com
2020-12-11 19:35     ` gautier...@hotmail.com
2020-12-11 22:40     ` Jeffrey R. Carter
2020-12-11 23:45       ` John Perry
2020-12-11 23:49     ` John Perry
2020-12-12  9:38       ` Maxim Reznik
2020-12-12 20:27   ` Stephen Leake

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox