How can I get anagrams of a word in ada programming. For example:
I have a string 'one'. How can it be jumbled into 'neo' or 'eon' etc?
example code:
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
WordText : String (1 .. 80);
Last : Natural;
begin
Put_Line("Enter Text: ");
Get_Line (WordText, Last);
-- example: I entered 'one'
-- it must be shuffle text per character
-- then it will print shuffled text: 'neo' or 'eno' or 'oen' etc.
Put_Line ("Text Shuffle: " &WordText (1 .. Last));
end Main;
Implement one of the jumble algorithms described here and here. For example,
For each word in a dictionary, sort its constiuent letters, preserving duplicates. Use an instance of Ada.Containers.Generic_Array_Sort to sort the letters.
Create a hash map; enter the sorted string as the map's key; add the original word to the set of words that are permutatively equivalent, and use the set as the map's value. Use an instance of Ada.Containers.Ordered_Sets to hold the set of words. Use an instance of Ada.Containers.Hashed_Maps for the map.
For a given string, sort its letters, look up the mapped set and print the words it contains.
A complete example is seen here.
Related
I'm in the process of making my own package for an Ada main program. I read a string followed by an integer and another string and the problem is I need to cut the first string at sign of first space. I don't know how to do it and I've searched stack overflow only to find solutions in other languages.
My code right now in the package body is:
Get_Line(Item.String, Item.X1)
where X1 is an integer and String is the string. This works if you define the length in the type to match the exact length of your input but of course you want to be able to insert whatever you want and thus it doesn't work.
Can somebody point me in the right direction?
Thanks
Why do you need to make a package for an Ada main program? Most compilers need them to be parameterless library-level procedures.
Anyway, this might give you some tips.
with Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Agrell is
begin
declare
Line : constant String := Ada.Text_IO.Get_Line;
This is how to deal with reading a string of unknown length. You have to work out how to preserve it for future use (maybe use an Unbounded_String?)
The_Integer : Integer;
begin
Looking_For_Space :
for J in Line'Range loop
if Line (J) = ' ' then
Everything from Line’First to J - 1 is the string you wanted.
declare
Dummy : Positive;
begin
Ada.Integer_Text_IO.Get (From => Line (J .. Line'Last),
Item => The_Integer,
Last => Dummy);
end;
OK, now we have The Integer...
...
exit Looking_For_Space;
... and we’re done with the first line.
end if;
end loop Looking_For_Space;
end;
end Agrell;
I'm trying to replace some characters in a String From a map
Case 1
map= ['O':'0', 'L':'1', 'Z':'2', 'E':'3']
"Hey".toUpperCase().toCharArray().each{
print map.get(it,it)
}
The result is
HEY
Case 2 : I dont use toCharArray()
"Hey".toUpperCase().each{
print map.get(it,it)
}
The result is like expected
H3Y
So I tried several alternatives when using toCharArray(), and the only way to access the value is to use map."$it"
Why i can only use map."$it" to access my map when using toCharArray() ?
Because you are trying to get a value from a map using a char whilst every key there are String, and they are not equals:
assert !'E'.equals('E' as char)
$it works because it is converted to String:
e = 'E' as char
assert "$e".toString().equals('E')
(Note the toString() is needed, otherwise the comparison will happen between String and GStringImpl which are not equals)
I am new to Ada programming.This is my ADA CODE for a program which gives me a list of things when typed a Football legend name in execution time.But I am getting the following errors.Please help me out:
Some of the Errors found are:
1.Discriminants must have a discrete or Access type
2.components "FBClubs cannot be used before end of record declaration
3.discriminant in a variant part must be of discrete part
4."player" is undefined
5."pos" is undefined.
6.no candidate interpretations match the sctuals : = > in call to inherited operation "to_string" at line "type playernames..."
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Integer_Text_Io; use Ada.Integer_Text_Io;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
Procedure football_record is
type Position is (Goalkeeper,Midfielder,Forward,Defender);
type playernames is new Unbounded_String;
type FBClubs is (ACMilan,Man_United,Aresnal,ParisSt.Germain,Real_Madrid,Liverpool,Chelsea,Man_City,Lille,
Tottenham,Ajax,Juventus,Dortmund,Roma,Santos,Roma,Bayern_Munich,Inter_Milan);
type countries is (England,Argentina,Brazil,France,Italy,Portugal,Spain,Germany,Iran,Japan);
type fbplayer(player:playernames) is
record
WCAppearances:Integer;
pos:Position;
country:countries;
fbclubs:FBClubs;
case player is
when "David Beckham" =>
country:countries:=England;
WCAppearances:Integer:=3;
pos:Position:=Midfielder;
fbclubs:FBClubs:=ACMilan &"+" & Man_United &"+" & Real_Madrid &"+"& ParisSt.Germain;
when "Lionel Messi" =>
country:countries:=Argentina;
WCAppearances:Integer:=1;
pos:Position:=Forward;
fbclubs:FBClubs:=Barcelona;
.....and some other 12 players(legends)..
when others =>
country:countries:=Nil;
WCAppearances:Integer:=Nil;
pos:Position:=Nil;
fbclubs:FBClubs:=Nil;
end case;
end record;
begin
Get(player);
Put_Line(To_String(Integer'Image(player)));
Put_Line(To_String(Integer'Image(FBClubs'Image(fbclubs)));
Put_Line(To_Unbounded_String(Position'Image(pos)));
end football_record;
The biggest problem is that you're mixing code in with a type declaration.
In Ada, putting a case within a record is only for variant records; these are records where some fields exist in certain cases but not others. For example:
type Employee_Type is (Regular, Manager);
type Employee (Emp_Type : Employee_Type) is record
Name : Unbounded_String;
case Emp_Type is
when Manager =>
Managerial_Level : Integer;
when Regular =>
null;
end case;
end record;
This is a variant record; we're assuming here that there are two kinds of employees, and the Managerial_Level field makes sense only for one of those kinds. Records whose type is Regular will not have a Managerial_Level field at all.
This syntax isn't what you would use to return different values of fields. Instead, you need to do this in statements, usually in a procedure or function (or package initialization, or some other places that allow statements).
And since you're not using the variant record syntax, you don't need to make player a discriminant. It doesn't work, anyway; in Ada, a "discriminant" (like Emp_Type in my example) has to be a discrete type like an integer or an enumeration type (Employee_Type is an enumeration type), or an access (access discriminants are an advanced concept). It can't be an Unbounded_String. So you'd want to make player a regular field:
type fbplayer is record
player : Unbounded_String;
pos : Position;
country : countries;
clubs : FBClubs; -- Note name change!
WCAppearances : Integer;
end record;
and create a procedure to fill in the fields:
procedure Fill_In_Player(P : in out fbplayer; Player : Playernames) is
begin
P.Player := Player;
if Player = "David Beckham" then
P.country := England;
P.WCAppearances := 3;
P.pos = Midfielder;
P.clubs := ??? -- see below
elsif Player = "Lionel Messi" then
------- etc.
elsif ------
end if;
end Fill_In_Player;
and then call Fill_In_Player when you have the Player and want to set up the record fields. You have to write statements to do this; you can't do it inside the declaration of a record.
Note that in Ada, case statements can only be used on integer or enumeration types. You can't use them to test for a string, as some other languages allow.
Ada does not treat lower-case and upper-case letters the same in identifiers or keywords. Therefore, fbclubs is the same name as FBClubs, and you can't declare the field
fbclubs : FBClubs;
because of the name conflict. I changed the name.
Finally, it looks like you want FBClubs to hold more than one club. But FBClubs is an enumeration type, and can therefore hold only one value at a time. If you want each player record to contain a list of clubs, you'll need to do something else, such as using one of Ada's container types (like Ada.Containers.Vectors.Vector) or something like
type Set_Of_Clubs is array(FBClubs) of Boolean;
where each array value is true if the player played for that club.
I'm not sure that will take care of all your errors, but it looks like you have a lot of work to do already.
i'm having some issues on bison (again).
I'm trying to pass a string value between a "recursive rule" in my grammar file using the $$,
but when I print the value I have passed, the output looks like a wrong reference ( AU�� ) instead the value I wrote in my input file.
line: tok1 tok2
| tok1 tok2 tok3
{
int len=0;
len = strlen($1) + strlen($3) + 3;
char out[len];
strcpy(out,$1);
strcat(out," = ");
strcat(out,$3);
printf("out -> %s;\n",out);
$$ = out;
}
| line tok4
{
printf("line -> %s\n",$1);
}
Here I've reported a simplified part of the code.
Giving in input the token tok1 tok2 tok3 it should assign to $$ the out variable (with the printf I can see that in the first part of the rule the out variable has the correct value).
Matching the tok4 sequentially I'm in the recursive part of the rule. But when I print the $1 value (who should be equal to out since I have passed it trough $$), I don't have the right output.
You cannot set:
$$ = out;
because the string that out refers to is just about to vanish into thin air, as soon as the block in which it was declared ends.
In order to get away with this, you need to malloc the storage for the new string.
Also, you need strlen($1) + strlen($3) + 4; because you need to leave room for the NUL terminator.
It's important to understand that C does not really have strings. It has pointers to char (char*), but those are really pointers. It has arrays (char []), but you cannot use an array as an aggregate. For example, in your code, out = $1 would be illegal, because you cannot assign to an array. (Also because $1 is a pointer, not an array, but that doesn't matter because any reference to an array, except in sizeof, is effectively reduced to a pointer.)
So when you say $$ = out, you are making $$ point to the storage represented by out, and that storage is just about to vanish. So that doesn't work. You can say $$ = $1, because $1 is also a pointer to char; that makes $$ and $1 point to the same character. (That's legal but it makes memory management more complicated. Also, you need to be careful with modifications.) Finally, you can say strcpy($$, out), but that relies on $$ already pointing to a string which is long enough to hold out, something which is highly unlikely, because what it means is to copy the storage pointed to by out into the location pointed to by $$.
Also, as I noted above, when you are using "string" functions in C, they all insist that the sequence of characters pointed to by their "string" arguments (i.e. the pointer-to-character arguments) must be terminated with a 0 character (that is, the character whose code is 0, not the character 0).
If you're used to programming in languages which actually have a string datatype, all this might seem a bit weird. Practice makes perfect.
The bottom line is that what you need to do is to create a new region of storage large enough to contain your string, like this (I removed out because it's not necessary):
$$ = malloc(len + 1); // room for NUL
strcpy($$, $1);
strcat($$, " = ");
strcat($$, $3);
// You could replace the strcpy/strcat/strcat with:
// sprintf($$, "%s = %s", $1, $3)
Note that storing mallocd data (including the result of strdup and asprintf) on the parser stack (that is, as $$) also implies the necessity to free it when you're done with it; otherwise, you have a memory leak.
I've solved it changin the $$ = out; line into strcpy($$,out); and now it works properly.
I have a function that returns a string for a particular item, and I need to call that function numerous times and combine those strings into one. The combined string is bounded. I've made sure to fill it when space characters when it initializes but I keep getting "length check failed" errors. Is there something basic I'm doing wrong here?
FOR I IN 1..Collection.Size LOOP
Combined_String := combined_string & Tostring(Collection.Book(I));
END LOOP;
Unbounded_String is probably the easiest way to go:
with Ada.Strings.Unbounded;
use Ada.Strings.unbounded;
...
Temp_Unbounded_String : Unbounded_String; -- Is empty by default.
...
for I in 1 .. Collection.Size loop
Append(Temp_Unbounded_String, ToString(Collection.Book(I));
end loop;
If you then need to have the result placed in your fixed length standard string:
declare
Temp_String : constant String := To_String(Temp_Unbounded_String);
begin
-- Beware! If the length of the Temp_String is greater than that of the
-- fixed-length string, a Constraint_Error will be raised. Some verification
-- of source and target string lengths must be performed!
Combined_String(Temp_String'Range) := Temp_String;
end;
Alternatively, you can use the Ada.Strings.Fixed Move() procedure to bring the Unbounded_String into the target fixed-length string:
Ada.Strings.Fixed.Move(To_String(Temp_Unbounded_String), Combined_String);
In this case, if the source string is "too long", by default a Length_Error exception is raised. There are other parameters to Move() that can modify the behavior in that situation, see the provided link on Move for more detail.
In order to assign Combined_String, you must assign the full correct length at once. You can't "build up" a string and assign it that way in Ada.
Without seeing the rest of your code, I think Ada.Strings.Unbounded is probably what you should be using.
I know this is an ancient question, but now that Ada 2012 is out I thought I'd share an idiom I've been finding myself using...
declare
function Concatenate(i: Collection'index)
is
(tostring(Collection(i) &
if (i = Collection'last) then
("")
else
(Concatenate(i+1))
);
s: string := Concatenate(Collection'first);
begin
Put_Line(s);
end;
Typed off the top of my head, so it'll be full of typos; and if you want it to work on empty collections you'll need to tweak the logic (should be obvious).
Ada 2012's expression functions are awesome!
Ada works best when you can use perfectly-sized arrays and strings. This works wonderfully for 99% of string uses, but causes problems any time you need to progressively build a string from something else.
Given that, I'd really like to know why you need that combined string.
If you really need it like that, there are two good ways I know of to do it. The first is to use "unbounded" (dynamically-sized) strings from Ada.Strings.Unbounded, as Dave and Marc C suggested.
The other is to use a bit of functional programming (in this case, recursion) to create your fixed string. Eg:
function Combined_String (String_Collection : in String_Collection_Type) return String is
begin
if String_Collection'length = 1 then
return String_Collection(String_Collection'first);
end if;
return String_Collection(String_Collection'first) &
Combined_String (String_Collection'first + 1 .. String_Collection'last);
end Combined_String;
I don't know what type you used for Collection, so I'm making some guesses. In particular, I'm assuming its an unconstrained array of fixed strings. If it's not, you will need to replace some of the above code with whatever your container uses to return its bounds, access elements, and perform slicing.
From AdaPower.com:
function Next_Line(File : in Ada.Text_IO.File_Type :=
Ada.Text_Io.Standard_Input) return String is
Answer : String(1..256);
Last : Natural;
begin
Ada.Text_IO.Get_Line(File => File,
Item => Answer,
Last => Last);
if Last = Answer'Last then
return Answer & Next_Line(File);
else
return Answer(1..Last);
end if;
end Next_Line;
As you can see, this method builds a string (using Get_Line) of unlimited* length from the file it's reading from. So what you'll need to do, in order to keep what you have is something on the order of:
function Combined_String (String_Collection : in String_Collection_Type)
Return String is
begin
if String_Collection'length = 1 then
Return String_Collection(String_Collection'First).All;
end if;
Recursion:
Declare
Data : String:= String_Collection(String_Collection'First).All;
SubType Constraint is Positive Range
Positive'Succ(String_Collection'First)..String_Collection'Last;
Begin
Return Data & Combined_String( String_Collection(Constraint'Range) );
End Recursion;
end Combined_String;
Assuming that String_Collection is defined as:
Type String_Collection is Array (Positive Range <>) of Access String;
*Actually limited by Integer'Range, IIRC