Eliminate multiple of couple of numbers - fortran

I have this simple program that create a list of two digit from 1 to 7:
1 1
1 2
1 3
1 4
...
and so on.
The condition I want is complicated because I want to EXCLUDE multiples of the two numbers: if I have 1,2 printed I don't want also 2,4 . And so on.
The f90 program is very simple:
program multiple
implicit none
integer :: i,j
i=0
j=0
do i= 1,7
do j =1,7
print*, i,j
end do
end do
end program
The question is: what IF (or other criteria) I must implement to eliminate digits of the form:
2 4
2 6
3 6
that are the multiples of 1,2 ; 1,3 ; 1,2 ?

If the largest value that either digit can take is 7 this ought to work:
Rewrite each pair of digits as a rational number with denominator 5040. I leave it as an exercise to figure out why I chose that denominator. So (2,3) would become 3360/5040. Of course, since the numbers have a common denominator you don't need to store that.
Now you have a mapping from your list of pairs to a list of integers; all the pairs which are equivalent by your rule (ie (1,2),(2,4),(3,6), ...) map to the same integer (in this case 2520).
There is a variety of ways to use this list of integers to write a loop to print only one of the pairs which maps to it.
This should be enough to get you started. If you have problems turning this into Fortran update your question with your best attempt and I (or someone else) will help you finish it.

I'm not entirely clear on the specifics, but it's simple enough to just show the general case.
In simple terms, i is your "outer loop" and first number, and j is your "inner loop" and second number. If you want to skip pairs containing a specific second number, the if goes around the print statement. If you want to skip pairs containing a specific first number, the if goes around the inner loop.
But, you want to skip the loop if the index is not your target value.
To see what both looks like in a program (2, 5, 3, and 6 could be any numbers):
do i= 1,7
if i /= 2 .and. i /=5 then
do j =1,7
if j /= 3 .then. j /= 6 then
print*, i,j
end if
end do
end if
end do
So, in this case, you'll only execute the j loop when i isn't 2 or 5. When you execute the inner loop, it will only print when j isn't 3 or 6.

Another approach would be to declare an array of logicals, such as
logical, dimension(7,7) :: found
Set every element to .false.. Then read your list of pairs of numbers. When you encounter a pair such as (2,4) you first reduce the fraction it represents (ie to (1,2)), then you set the corresponding element of found to .true..
After one run through your list of pairs of integers the array found contains .true. at precisely those locations whose indices are the pairs you are looking for.
This doesn't quite work if your list contains, say, (2,4) and (3,6) but not (1,2) and your desired output is (2,4), that is the first of the pairs which occurs. But I expect you could adapt it for this situation too.

Related

How to find elements of a string that cannot be part of a non contigous substring?

I want to write a program that takes 2 strings as input, s1 and s2, and determines which characters of s1 couldn't be part of a non contigous substring that is 2. So after inputting
123625421454 as s1, and 254 as s2, the program would output
0 1 0 0 1 1 1 1 0 1 1 1, where 1 means that a character can be a part of the substring, and 0 where it cannot.
This problem is really irritating me, since I couldn't find any algorithm that would find the non-contigous sequence without extremely high execution time. Is there even a good solution for this, with less or equal O than O(N)?
I have tried to use hashes and dynamic programming, but no algorithms that I used were good for this circumstance.
EDIT: To clarify, the idea is that you can remove x elements of s1 (x can be 0) and get s2. Elements, which cannot be part of s2 under any circumstances, should be marked as 0, while those that can, should be marked as 1. Hope this helps.
A key observation is, if you reach a sub-substring prefix of length k up to a position, then you can have a sub-substring of any length less than k up to that position, simply by skipping some of the tail elements. Same holds for postfix. It might sound trivial, but it leads to the solution.
So you'd like to maximize the prefix from front and postfix from tail. Basically, this means that you visit s1 once from front and once the reverse (with reverse s2). In both cases, you'd like to maximize the substring at each point, so you simply advance in s2 whenever you can. This gives you two array of size_t values: longest possible prefix and postfix at the given point. If the sum of those >= the length of s2 (and there was an increase at the current character in prefix/postfix arrays compared to previous), that means that these can be joined and the result is 1; otherwise these cannot be joined and the result is 0.
To do this, you actually need to precalculate if a given char can be an increase at a position in s2. This can be done in O(1) time (see chat for elaboration on that).

Match all numbers present in two arrays efficiently [Python]

I want to match numbers that are present in two arrays (not of equal length) and output them to another array if there is a match. The numbers are floating point.
Currently I have a working program in Python but it is slow when I run it for large datasets. What I've done is two nested for loops.
The first nested for loop runs through array1 and checks if any numbers from array2 are in array 1. If there is a match, I write it to an array called arrayMatch1.
I then check array2 and see if there is a match with arrayMatch1. And output the final result to arrayFinal.
arrayFinal will have all numbers that exist within both array1, array2.
My problem:
Two nested for loops give me a complexity of O(n^2). This method works fine for data sets under an array length of 25000 but slows down significant if greater. How can I make it more efficient. The numbers are floating point and always are in this format ######.###
I want to speed up my program but keep using Python because of the simplicity. Are there better ways to find matches between two arrays?
Why not just find the interesection of two lists?
a = [1,2,3,4.3,5.7,9,11,15]
b = [4.3,5.7,6.3,7.9,8.1]
def intersect(a, b):
return list(set(a) & set(b))
print intersect(a, b)
Output:
[5.7, 4.3]
Gotten from this question.
So what you're basically trying to do is find intersection(logically correct term) of 2 list.
First you need to eliminate the duplicate form the list itself, set is great way to do that, then you can just & those lists and you will be good to go.
a = [23.3213,23.123,43.213,12.234] #List First
b = [12.234,23.345,34.224] #List Second
def intersect(a, b):
return list(set(a) & set(b))
print intersect(a, b)

How to force jumps with std::next_permutation

Is it possible to manipulate the current permutation sequence in order to skip (in my case) "useless" sequences?
If that isn't possible, would a custom implementation of a permutation iteration be as fast as std::next_permutation?
An example:
1 2 3 4 5 6 7 ...
1 3 2 4 5 6 7 ...
Detecting that "2" at the 2nd position isn't valid, leads to skipping every permutation which begins with "1, 2".
You would have to write some custom rules for that. A smart way to do this would be to write a code, in which whenever you have a set of permutations which are not valid, you jump to the next permutation you can get which will be valid.
For eg, in the above case, knowing that 2 at 2nd position is invalid, you could write the code to swap 2 and 3, and ensure that the permutation then achieved is the smallest one possible with 3 in that location, and so on.
Also, if you were writing your own implementation of next_permuation, ensure that the internal functioning is as close to that of next_permutation. You can read about it here: std::next_permutation Implementation Explanation
Yes, this is possible, and it's not hard once you understand how next_permutation works.
In short, there are N! permutations of N items. However, only one of them is sorted. 1 2 3 4 5 6 7 for instance is the first of 5040 permutations. Viewed as a string (lexicographically) the next permutation is the one that sorts directly after that: 1 2 3 4 5 7 6. It particular, the first 5 elements are unaltered. The next permutation alters the 5th element because the last 2 elements are in reverse order.
So, in your case, once you've found an illegal permutation, you'd have to explicitly calculate the next legal permutation by sort order. If 1 2 is the only illegal prefix then 1 3 2 4 5 6 7 is obviously the next valid permutation.
In general, look at your illegal pattern, determine which positions you have to increase because they violate constraints, and come up with the next valid values for those positions (if your pattern is small enough, you can brute-force this). Then fill in the remaining numbers in sorted order.

Declaring functions

I'm very new to haskell programing and have alot of difficulties quite sometime. The task I'm given here is that a have a list of numbers it then compares to another list of numbers and returns three numbers as feedback based on which interpretation on other numbers could be filtered.
eg.
[4,9],[7,9],[10,18],[2,9] is my list
it should two separate lists now [4,9] and [7,9] it should give a feedback (1,1,0)
first function should check whether two lists have the same value if they have then it should return value 2, if there is only one value then it should return 1, no values then it returns 0
i tried to do this with elem method but im not able to succeed . So the answer for this must be 1 since it has 9 on both lists.
second function checks for the lowest value. It should only compare from the second element to the first. from the same example above [4,9] and [7,9] it first finds out the lowest value in [7,9] which is 7 and then checks for any value lower than 7 in [4,9], it there then it returns a feedback 1 else its 0
third function is the same as the second except it checks for the highest value
eg . [[3,13],[10,9],[5,7]] we take first two elements of the list
[3,13] and [10,9], now we check the highest number in [10,9] which is 10 and check for that value in [3,13] here the answer must be 1 since 13 is higher than 10 else it is 0
please help in declaring these functions
would be much obliged
Your question is a bit confusing without seeing any sample code. I think I understand how your first function needs to work:
It seems that you are using a list of lists, [[Int]] but all of your lists only have two items. It would be easier to use a pair [(Int,Int)]
Then your first function could be written with nested if statements:
firstTest (a1,b2) (a2,b2) = if a1 == a2 && b1 == b2 then 2 else if a1 == a2 || b1 == b2 then 1 else 0
If it can't be a pair and it must be a list of lists then it might be easier to reify your problem and turn the two lists into Sets using Data.Set. Comparing two sets is far more efficient than comparing two lists - and Data.Set provides us the useful isSubsetOf function. You can transform a list into a set using the fromList function.
import qualified Data.Set as S
firstTest' :: S.Set Int -> S.Set Int -> Int
firstTest' sas sbs = if sas == sbs then 2 else if S.isSubsetOf sas sbs then 1 else 0
Comparing adjacent items in a list is a bit challenging. Take a look at my answer to this question: https://stackoverflow.com/a/25777940/3792504

How to read a list of integers from an input line

Is it possible to read a line with numerous numbers(integers) using Fortran?
lets say i have a file with only only line
1 2 3
the following program reads 3 integers in a line
program reading
implicit none
integer:: dump1,dump2,dump3
read(21,*) dump1,dump2,dump3
end
so dump1=1 dump2=3 dump3=3
If i have a file with only one line but with numerous integers like
1 2 3 4 5 6 7 8 ... 10000
is ti possible the above program to work without defining 10000 variables?
EDIT The first paragraph of this answer might seem rather strange as OP has modified the question.
Your use of the term string initially confused me, and I suspect that it may have confused you too. It's not incorrect to think of any characters in a file, or typed at a command-line as a string, but when all those characters are digits (interspersed with spaces) it is more useful to think of them as integers. The Fortran run-time system will
take care of translating a string of digit characters into an integer.
In that light I think your question might be better expressed as How to read a list of integers from an input line ? Here's one way:
Define an array. Here I define an array of fixed size:
integer, dimension(10**4) :: dump
(I often use expressions such as 10**4 to avoid having to count 0s carefully). This step, defining an array to capture all the values, seems to be the one you are missing.
To read those values from the terminal, at run-time, you might write
write(*,*) 'Enter ', 10**4, 'numbers now'
read(*,*) dump
and this will set dump(1) to the first number you type, dump(2) to the second, all the way to the 10**4-th. Needless to say, typing that number of numbers at the terminal is not recommended and a better approach would be to read them from a file. Which takes you back to your
read(21,*) dump
It wouldn't surprise me to find that your system imposes some limit on the length of a single line so you might have to be more sophisticated when trying to read as many as 10**4 integers, such as reading them in lines of 100 at a time, something like that. That's easy
read(*,*) dump(1:100)
will read 100 integers into the first 100 elements of the array. Write a loop to read 100 lines of 100 integers each.