Looping in filemaker using a local variable - filemaker

Been programming in C# for a little bit - trying to use file maker and I cant believe it but I cant even get a simple for loop to work.
What I want to do is simple: loop through for the amount of entries in my "amountOfRooms" field and create an entry in a table for each room.
Sounds so simple, but I cant get it to work. Right now I have this:
Set Variable[$cnt[Customers::AmountOfRooms]; value:1]
Go to Layout["rooms"(Rooms)]
Loop
Exit Loop If[$cnt = Customers::AmountOfRooms]
New Record / Request
Set Variable[$cnt; Value: $cnt + 1]
End Loop
Exit Script
No new records are created. I know the script is running because it does go to my layout, but doesnt create any new records. There is a "Repetition" field for my local variable - not sure how to use that or what it means? Any thoughts on how to do this simple loop? Thanks.

Loop
Depending on your relationship, the line Exit Loop If[$cnt = Customers::AmountOfRooms] might be equal at the first iteration because you set the variable to the value three lines above it: Set Variable[$cnt[Customers::AmountOfRooms]; value:1]
There are other ways to do it, but one common technique is to have a $i variable compare against $cnt like this:
Set Variable [$cnt; Value:Customers::AmountOfRooms]
Go to Layout ["Rooms" (Rooms)]
#
Set Variable [$i; Value:1]
Loop
Exit Loop If [$i >= $cnt]
New Record/Request
Set Variable [$i; Value:$i + 1]
End Loop
Exit Script []
Repetition Number
At a high level, you can think of a FileMaker variable as a 1-indexed array. So the statements:
# Set Repetition 1 of $i to 1
Set Variable [$i; Value:1]
#
# Set Repetition 2 of $j to "Second Array Position"
Set Variable [$j[2]; Value:"Second Array Position"]
Would be equivalent to:
# Set the first value of array $i to 1
$i[0] = 1;
#
# Set the second value of array $j to "Second Array Position"
$j[1] = "Second Array Position";
in some other languages.
It's worth nothing that the array comparison is not strictly apt, but it's a good way to begin thinking of them. Regardless, you don't need to worry about the repetition number in this instance. If you want to learn more, you can start here: http://www.filemaker.com/11help/html/scripts_ref1.36.15.html

Related

Processing a list with Powershell on a Scheduled Task

I'm a newbie to powershell, so I'm not sure if I am over thinking what I want to do, hopefully somebody can help me out.
I want to create a Windows scheduled task that calls my powershell script every 4 hours, no problems there. The script needs to process a list of ID's that range from 1 to 140,(They skip a few here and there which makes this harder) the script is just calling another external program that takes about 2 hours per ID, we give it 4 hours to be safe. So upon the powershell script loading, it needs to read from a file the last scan it did, I can do that using
$lastscan = Get-Content'lastScan.txt'
Then the script needs to find the next object in the list, which may skip a number here or there so it's not as simple as just incrementing the last scan run. Once it has the next ID it will kick off the scan and save the new value to the text file named "lastScan.txt" and exit. The only thing I need help with, is how to find the next scan in my list based on the lastscan run. The list is seperated by newline, but I could edit it if it makes it easier.
1
5
6
9
etc, etc, ...
Assuming you have a string array that was populated with Get-Content and assuming the array did not contain duplicates, you could use the Array.IndexOf method to get the index of the current id and then return the next element in the array. Example:
$x = "1","2","3"
$currentId = "2"
$nextIndex = [array]::IndexOf($x, "2") + 1
$nextId = $x[$nextIndex] #nextId should now be "3"

Using strmatch in a loop

Can I do the something below coded using or without loop?
Actually I am having a character array comprising of unique words more than 5000 and other array comprising of approx 3000 words. I want to search each word in my array named as word in other array named as uniques and wish to create a feature vector i.e. values 1 if exists and 0 if doesn't.
I am doing the following..
load 'uniques' %uniques={'alpha','ok',abc'};
fid=fopen(myfilename);
words=textscan(fid,'%s');
fclose(fid);
word=words{1,1}; %word={'good','bad',anywhere','countries','ok',done','abc'}
for i=1:size(uniques,2)
ind=strmatch(word(i), uniques, 'exact');
end
Now, seeing above as examples before uniques and word arays, my system must return 0 for good as good is not there in uniques and same 0 values but 1 for ok because it does exist in uniques. All in all, I must have in the end, {0,0,0,0,1,0,1} ..
After I run, it gives me ind=[]
Please guide
You have described the exact functionality of the ismember function:
ismember(word, uniques);
as an aside, this is what #nkjt was saying about fixing your loop:
for i=1:size(word,2)
ind(i)=strmatch(word(i), uniques, 'exact');
end
But this loop is unnecessary since Matlab has this as a built in function

Perl "else" statement not executing

I use an ActivePerl script to take in CSV files and create XML files that I load into a database. These are userid database entries, name, address, etc. We've always used the home phone number field to generate an initial password (which we encourage the users to change immediately!). The proliferation of cellphones means I have a bunch of people with no home phone, so I want to use the cell phone field when the home phone field is empty.
My input fields look like this:
# 0 Firstname
# 1 Lastname
# 2 VP (voicepart)
# 3 Address
# 4 City
# 5 State
# 6 Zip
# 7 Phone
# 8 Mobile
# 9 Email
Here's the Perl code I've worked up to create the password - the create_password subroutine is working when there's a value in field 7:
my $pass_word = '';
my $pass_word = create_password($fields[7]);
if (my $pass_word = '') {
print "Use the cell phone number \n";
my $pass_word = create_password($fields[8]);
}
The "print" statement is to tell me what it thinks it's doing.
This looks to me like it should work, but the "if" statment never fires. The Print statement doesn't print, and nobody with a value only in field 8 ever gets a password generated. There must be something wrong with the way I'm testing the value of $pass_word but I can't see it. Should I be testing the values of $fields[7] and $fields[8] instead of the variable value? How DO you test a Perl variable for null value if this doesn't work?
You have several problems in your code.
First of all, after you declared a variable using my, you don't need to add my before the variable when you use it;
Secondly, for this line:
if (my $pass_word = '')
I think you meant
if ($pass_word == '')
(my is removed, as talked in the first point)
= means assignment, which returns the value you assigned to $pass_word, which is '' here, that's why this condition always return false.
But still, == is not correct here. In perl, we use eq to compare two strings. == is used to compare numbers.
So, remove all the my except the first one, and use eq to compare your strings.
You've got two major problems in here.
First one is your string equality test. In Perl, strings are compared for equality using operator eq (as in $string eq 'something'). = is the assignment operator.
Second one is your (ab)use of my. Each my declares a new variable that “hides” the previous one, so in effect you can never re-use its value, you're confronted to undef every time.
Replace = with eq in your if clause; remove all but the first uses of my, and you should be set!
my declares a new variable which hides the variable with the same name in the surrounding scope. Remove the excessive use of my.

Need to add two values in perl

In if condition I used to take one value from log file after matching the particular pattern. That pattern is matched two times in log file. While matching the pattern first time that value is 0 and second time value is 48. It may be also reverse. First value may contain 48 and second value may contain 0. I need to calculate the exact value. So I planned to add these two values. but after adding these two values also while printing the total value in if condition I used to get the two values separately. But I need single value only.
Please give me solution to solve this issue.
Thanks in advance.
Do you mean something like this:
my $entry = "First is 10, seconds is 48";
if(my ($a,$b) = $entry =~ /(\d+)/g) {
print $a + $b,"\n"; # 58
}
But without actual code it is hard to see what your problem really is.

Find combinations of numbers that sum to some desired number

I need an algorithm that identifies all possible combinations of a set of numbers that sum to some other number.
For example, given the set {2,3,4,7}, I need to know all possible subsets that sum to x. If x == 12, the answer is {2,3,7}; if x ==7 the answer is {{3,4},{7}} (ie, two possible answers); and if x==8 there is no answer. Note that, as these example imply, numbers in the set cannot be reused.
This question was asked on this site a couple years ago but the answer is in C# and I need to do it in Perl and don't know enough to translate the answer.
I know that this problem is hard (see other post for discussion), but I just need a brute-force solution because I am dealing with fairly small sets.
sub Solve
{
my ($goal, $elements) = #_;
# For extra speed, you can remove this next line
# if #$elements is guaranteed to be already sorted:
$elements = [ sort { $a <=> $b } #$elements ];
my (#results, $RecursiveSolve, $nextValue);
$RecursiveSolve = sub {
my ($currentGoal, $included, $index) = #_;
for ( ; $index < #$elements; ++$index) {
$nextValue = $elements->[$index];
# Since elements are sorted, there's no point in trying a
# non-final element unless it's less than goal/2:
if ($currentGoal > 2 * $nextValue) {
$RecursiveSolve->($currentGoal - $nextValue,
[ #$included, $nextValue ],
$index + 1);
} else {
push #results, [ #$included, $nextValue ]
if $currentGoal == $nextValue;
return if $nextValue >= $currentGoal;
}
} # end for
}; # end $RecursiveSolve
$RecursiveSolve->($goal, [], 0);
undef $RecursiveSolve; # Avoid memory leak from circular reference
return #results;
} # end Solve
my #results = Solve(7, [2,3,4,7]);
print "#$_\n" for #results;
This started as a fairly direct translation of the C# version from the question you linked, but I simplified it a bit (and now a bit more, and also removed some unnecessary variable allocations, added some optimizations based on the list of elements being sorted, and rearranged the conditions to be slightly more efficient).
I've also now added another significant optimization. When considering whether to try using an element that doesn't complete the sum, there's no point if the element is greater than or equal to half the current goal. (The next number we add will be even bigger.) Depending on the set you're trying, this can short-circuit quite a bit more. (You could also try adding the next element instead of multiplying by 2, but then you have to worry about running off the end of the list.)
The rough algorithm is as follows:
have a "solve" function that takes in a list of numbers already included and a list of those not yet included.
This function will loop through all the numbers not yet included.
If adding that number in hits the goal then record that set of numbers and move on,
if it is less than the target recursively call the function with the included/exluded lists modified with the number you are looking at.
else just go to the next step in the loop (since if you are over there is no point trying to add more numbers unless you allow negative ones)
You call this function initially with your included list empty and your yet to be included list with your full list of numbers.
There are optimisations you can do with this such as passing the sum around rather than recalculating each time. Also if you sort your list initially you can do optimisations based on the fact that if adding number k in the list makes you go over target then adding k+1 will also send you over target.
Hopefully that will give you a good enough start. My perl is unfortuantely quite rusty.
Pretty much though this is a brute force algorithm with a few shortcuts in it so its never going to be that efficient.
You can make use of the Data::PowerSet module which generates all subsets of a list of elements:
Use Algorithm::Combinatorics. That way, you can decide ahead of time what size subsets you want to consider and keep memory use to a minimum. Apply some heuristics to return early.
#!/usr/bin/perl
use strict; use warnings;
use List::Util qw( sum );
use Algorithm::Combinatorics qw( combinations );
my #x = (1 .. 10);
my $target_sum = 12;
{
use integer;
for my $n ( 1 .. #x ) {
my $iter = combinations(\#x, $n);
while ( my $set = $iter->next ) {
print "#$set\n" if $target_sum == sum #$set;
}
}
}
The numbers do blow up fairly rapidly: It would take thousands of days to go through all subsets of a 40 element set. So, you should decide on the interesting sizes of subsets.
Is this a 'do my homework for me' question?
To do this deterministically would need an algorithm of order N! (i.e. (N-0) * (N-1) * (N-2)...) which is going to be very slow with large sets of inputs. But the algorithm is very simple: work out each possible sequence of the inputs in the set and try adding up the inputs in the sequence. If at any point the sum matches, you've got one of the answers, save the result and move on to the next sequence. If at any point the sum is greater than the target, abandon the current sequence and move on to the next.
You could optimize this a little by deleting any of the inputs greater than the target. Another approach for optimization would be to to take the first input I in the sequence and create a new sequence S1, deduct I from the target T to get a new target T1, then check if T exists in S1, if it does then you've got a match, otherwise repeat the process with S1 and T1. The order is still N! though.
If you needed to do this with a very large set of numbers then I'd suggest reading up on genetic algorithms.
C.
Someone posted a similar question a while ago and another person showed a neat shell trick to answer it. Here is a shell technique, but I don't think it is as neat a solution as the one I saw before (so I'm not taking credit for this approach). It's cute because it takes advantage of shell expansion:
for i in 0{,+2}{,+3}{,+4}{,+7}; do
y=$(( $i )); # evaluate expression
if [ $y -eq 7 ]; then
echo $i = $y;
fi;
done
Outputs:
0+7 = 7
0+3+4 = 7