I've programmed a stack of generic numbers in Ada using a 'Indefinite_Doubly_Linked_Lists' list.
Pop & push operations are implemented with append and delete_last but for a sorting method I would need to access individual items of the list.
I did work out a sorting method using only append/prepend delete_last/first but the result is far from elegant (and maybe not correct)
procedure sort is
elem1: Item;
elem2: Item;
--l is a package-private Indefinite_Doubly_linked_lists'
begin
if Integer(MyList.Length(l)) > 1 then
for i in 0 .. Integer(MyList.Length(l))-1 loop
for j in 0 .. Integer(MyList.Length(l))-1 loop
--Inner sort loop
elem1 := MyList.Element(l.first);
l.Delete_First;
elem2 := MyList.Element(l.first);
l.Delete_First;
if elem1>elem2 then
l.Prepend(elem1);
l.Append(elem2);
else
l.Prepend(elem2);
l.Append(elem1);
end if;
end loop;
end loop;
end if;
end;
How do can I access individual elements (or iterate over) from a list of generic type?
A couple things:
Unless the point of your exercise is writing a sort, you could just...uh...use the generic sort:
package List_Sort is new MyList.Generic_Sorting;
If you're using an Ada 2012 compiler, generalized looping gives you easy access to each element:
procedure Iterate is
begin
for Elem of L loop
Put_Line(Item'Image(Elem));
end loop;
end Iterate;
If you're not using Ada 2012, you can make due with cursors, either on their own:
procedure Cursor_Iterate is
C : MyList.Cursor := L.First;
use type MyList.Cursor;
begin
loop
exit when C = MyList.No_Element;
Put_Line(Item'Image(MyList.Element(C)));
MyList.Next(C);
end loop;
end Cursor_Iterate;
or with MyList's Iterate procedure:
procedure Iterate
(Container : in List;
Process : not null access procedure (Position : in Cursor));
Related
I'm quite new to Maple and I would like to create the following list:
U__N := u__1[0], u__2[0], u__1[1], u__2[1], u__1[2], u__2[2], u__1[3], u__2[3], u__1[4], u__2[4], u__1[5], u__2[5]
I came up with the following two options. For both I lack the knowledge for the last step
Option 1
U__N := seq([u__1[k], u__2[k]], k = 0 .. 5)
which gives me a nested list: U__N := [u__1[0], u__2[0]], [u__1[1], u__2[1]], [u__1[2], u__2[2]], [u__1[3], u__2[3]], [u__1[4], u__2[4]], [u__1[5], u__2[5]]. However, now I do not know how to "un-nest" the nested list.
Option 2:
Create two separate lists
U__N2 := seq(u__2[k], k = 0 .. 5 - 1)
which returns U__N1 := u__1[0], u__1[1], u__1[2], u__1[3], u__1[4]
U__N2 := seq(u__2[k], k = 0 .. 5 - 1)
which returns U__N2 := u__2[0], u__2[1], u__2[2], u__2[3], u__2[4].
Now I would like to concatenate/combine these two lists alternatively.
Do you have any suggestions for one of these two options or an alternative solution?
I would prefer to create the pair-wise portions and then utilize those directly, than to form the whole list-of-lists and Flatten it.
The special-evaluation rules of the seq command allows for its first argument to not be evaluated until after k attains concrete numeric values.
This allow you to adjust your first method and extract the operands of the pair-wise inner lists, using the op command.
seq(op([u__1[k], u__2[k]]), k = 0 .. 5);
u__1[0], u__2[0], u__1[1], u__2[1],
u__1[2], u__2[2], u__1[3], u__2[3],
u__1[4], u__2[4], u__1[5], u__2[5]
seq([u__1[k], u__2[k]][], k = 0 .. 5);
u__1[0], u__2[0], u__1[1], u__2[1],
u__1[2], u__2[2], u__1[3], u__2[3],
u__1[4], u__2[4], u__1[5], u__2[5]
The trailing [] in [...][] acts like op([...]).
using Flatten gave me the desired solution
I have data in the form of list of lists where I am trying to match the demand and supply such that each demand matches uniquely to one supply item.
dmndId_w_freq = [['a',4,[1,2,3,4]],['b',6,[5,6,7,8,3,4]],['c',7,[6,5,7,9,8,3,4]],['d',8,[1,6,3,4,5,6,7,10]]]
num_sims = 1
for sim_count in range(num_sims):
dmndID_used_flag = {}
splID_used_flag = {}
dmndID_splId_one_match = {}
for i in dmndId_w_freq:
if i[0] not in dmndID_used_flag.keys():
for j in i[2]:
#print j
#print "CLICK TO CONTINUE..."
#raw_input()
if j in splID_used_flag.keys():
i[2].remove(j)
dmndID_splId_one_match[i[0]] = i[2][0]
splID_used_flag[i[2][0]] = 1
dmndID_used_flag[i[0]] = 1
print
print dmndID_splId_one_match
#print splID_used_flag
#print dmndID_used_flag
#raw_input()
I would expect the output dmndID_splId_one_match to be something like {'a':1,'b':5,'c':6,'d':3}.
But I end up getting {'a':1,'b':5,'c':6,'d':6}
So I am NOT getting a unique match as the supply item 6 is getting mapped to demands 'c' as well as demand 'd'.
I tried to debug the code by looping through it and it seems that the problem is in the for-loop
for j in i[2]:
The code is not going through all the elements of i[2]. It does not happen with the 'a' and 'b' part. but starts happening with the 'c' part. It goes over 6 and 5 but skips 7 (the third element of the list [6,5,7,9,8,3,4]). Similarly, in the 'd' part it skips the 2nd element 6 in the list [1,6,3,4,5,6,7,10]. And that is why the mapping is happening twice, since I am not able to remove it.
What am I doing wrong that it is not executing the for-loop as expected?
Is there a better way to write this code?
I figured out the problem in the for loop. I am looping through i[2] and then trying to modify it within the loop. this makes it unstable.
I try to loop backwards in table.
I try it like this:
KlantContact.SETFILTER("No.", "<Contact>"."No.");
FOR i := 0 TO KlantContact.COUNT DO BEGIN
IF KlantContact.FINDSET THEN BEGIN REPEAT // KlantContact.FINDSET THEN BEGIN REPEAT
//KlantContact.CALCFIELDS(KlantContact."No.");
MESSAGE(KlantContact.Name);
UNTIL KlantContact.NEXT -1 = 0;
//MESSAGE(KlantContact.COUNT);
END;
END;
Thank you
Set the key, set descending order and loop through the table with REPEAT..UNTIL:
Record.RESET;
Record.SETCURRENTKEY("Field1","Field2");
Records.ASCENDING(FALSE);
IF Record.FINDSET(FALSE,FALSE) THEN BEGIN
REPEAT
// do something
UNTIL Record.NEXT = 0;
END;
If you want to modify the table use the parameters in FINDSET accordingly.
Cheers!
In Ada 2012, I want to have a linked list inside a declared array, rather than allocated. I want to have the linking pointers set by a procedure.
I have simplified my program to the following that demonstrates the principle I want to use but I cannot get this to compile in Gnat 4.9.2 (Debian Jessie) running on Raspi...
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Ch'First .. Ch'Last - 1 loop
Ch (I).Next := Ch (I + 1)'Access; -- ERROR HERE
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
I get this compiler error:
"non-local pointer cannot point to local object" at the line indicated above.
I know I'm trying to do something a bit odd but I plan on having a few other functions that perform the linking in different ways (backwards, or randomly etc) based on which procedure I pass this array of cells to.
How do I fix this code so that it compiles? Can't quite get my head around this one (I'm still a novice but enjoying the learning process).
As you are not actually allocating & freeing memory, in dont see the need for pointers. I would achieve the same functionality by doing something like this:
procedure Arr is
type Cell_Index is new Integer range 0 .. 100;
subtype Valid_Cell_Index is Cell_Index range 1 .. Cell_Index'Last;
type Cell is
record
Number : Integer := 0;
Next : Cell_Index := 0;
end record;
type Chain is array (Valid_Cell_Index) of Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Valid_Cell_Index'First .. Valid_Cell_Index'Last - 1 loop
Ch (I).Next := I+1;
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
This way you are still using Next as an index into the same array, and can pre-load your array with whatever linking pattern you want.
Instead of using ’Access, use ’Unrestricted_Access. This is one of GNAT’s “implementation-defined” attributes:
The Unrestricted Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute.
I figured it out in the end. The following code is a modified version of the one in the OP. It does what I originally wanted without doing anything unpleasant...
with Ada.Integer_Text_IO, Ada.Text_IO;
use Ada.Integer_Text_IO, Ada.Text_IO;
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
type Chain_Ptr is access all Chain;
procedure Make_Links (CP : in out Chain_Ptr);
procedure Make_Links (CP : in out Chain_Ptr) is
begin
for I in CP'First .. CP'Last - 1 loop
CP.all (I).Next := CP.all (I + 1)'Access;
end loop;
end Make_Links;
My_Chain : aliased Chain;
My_CP : Chain_Ptr := null;
My_C : Cell_Ptr := null;
begin
My_CP := My_Chain'Access;
Make_Links (My_CP);
-- verify that the code works by writing values into the array
for I in My_Chain'Range loop
My_Chain (I).Number := 1000 * I;
end loop;
-- and read them back out using the pointer links
My_C := My_Chain (My_Chain'First)'Access;
while My_C /= null loop
Put (My_C.Number);
Put_Line ("");
My_C := My_C.Next;
end loop;
end Arr;
Instead of passing the array directly, I passed a pointer to the array instead, which Gnat seems happy with. I think what I was trying to do before was being scuppered by the "pass by copy" rules for procedure parameters.
I've hit a complete dead end with this. This is probably going to be something incredibly basic and it will most likely result in me smashing my head into a wall for having a major brain fart. My question is basically, how do you loop though tables in lua if the entries are tables themselves?
C++:
lua_newtable(luaState);
for(auto rec : recpay) {
lua_newtable(luaState);
lua_pushnumber(luaState, rec.amount);
lua_setfield(luaState, -2, "Amount");
lua_pushnumber(luaState, rec.units);
lua_setfield(luaState, -2, "Units");
lua_setfield(luaState, -2, rec.type);
}
lua_setglobal(luaState, "RecuringPayments");
Lua:
for _,RecWT in ipairs(RecuringPayments) do
-- RecWT.Amount = nil?
end
In your C++ code it looks like you're setting the subtable by string as a key rather than by index. To traverse that entry you have to use pairs instead:
for recType, RecWT in pairs(RecuringPayments) do
assert(RecWT.Amount ~= nil)
end
Note that ipairs only traverses the index part of the table, the associative part is ignored.
Alternatively, if you want to use index access then you have to set the key-value with lua_settable instead:
lua_newtable(luaState);
int i = 0;
for(auto rec : recpay)
{
lua_newtable(luaState);
lua_pushnumber(luaState, rec.amount);
lua_setfield(luaState, -2, "Amount");
lua_pushnumber(luaState, rec.units);
lua_setfield(luaState, -2, "Units");
lua_pushnumber(luaState, ++i);
lua_insert(luaState, -2);
lua_settable(luaState, -3);
}
lua_setglobal(luaState, "RecuringPayments");
You can use a recursive function that traverses tables:
function traversetable(tab, array)
local iteratefunc = array and ipairs or pairs
for k, v in iteratefunc(tab) do
if type(v) == "table" then
traversetable(v, array) --Assumes that type is the same as the parent's table
else
--Do other stuff
end
end
end
This is just a basic example, but gives you a rough idea. array is a boolean value indicating, whether it's a one-based array or not.