How do I form characters design with do loop - fortran

I am trying to make characters with an output as such in Fortran but I don't know how to. I made one with columns of asterisks but now I need it to change to the image linked.
I am a novice at Fortran.
Here's my code for the columns:
program chardesign
integer complete
do complete = 1, 5
write (*, 10, advance='no')
10 format (' * ')
enddo
!Newline to complete
write (*, 10)
stop
end program chardesign
How can I go about this?

Since we can no longer restrain ourselves from offering solutions...
Suppose we had a file called diamond.txt that had the picture already drawn:
*
***
*****
*******
*********
*******
*****
***
*
I know it's not visible here, but each line in diamond.txt has sufficient trailing spaces to make it 9 characters long. Now we just need a program that copies diamond.txt to its output:
program diamond
implicit none
character(9) line
open(10,file='diamond.txt',status='old')
do
read(10,'(a)',end=20) line
write(*,'(a)') line
end do
20 continue
end program diamond
The program has a couple of new features: first off it has implicit none which forces the programmer to declare all variables, thus avoiding a common source of hard-to-trace programming errors. Then it declares a character variable character(9) line which creates a variable which always contains 9 characters. There are rules that govern what happens if you try to assign it to a string of lesser or greater length, but we won't do that here.
Then it opens the file diamond.txt. The unit number, 10, will be used to reference the file in subsequent I/O statements. The status='old' part will cause the program to abort if it can't find diamond.txt.
Then we have a do statement which means do forever. Of course we don't really want to 'do forever', so there should be some way to exit the loop from its body.
Now we have a read statement that reads from unit 10, which, due to our previous open statement, is our file diamond.txt. The end=20 part means that when the read statement tries to read past end-of-file execution jumps to statement number 20, which gets us out of the loop. The format (a) does character I/O. It is the same as (a9) because the program knows that the length of the character variable to be read, line, is 9, so it will try to read the next 9 characters from diamond.txt and put them in variable line. After the read statement is complete, the file pointer advances to the next line of diamond.txt.
Then the write statement just writes variable line to standard output, thus copying the current line of diamond.txt to the screen.
When it's done, the end=20 branch is taken getting us to the 20 continue statement after which the end line is encountered and execution terminates.
So how could we do this without an external file? We could just convert the picture into a format statement and then print according to the format:
1 format(' * '/ &
' *** '/ &
' ***** '/ &
' ******* '/ &
'*********'/ &
' ******* '/ &
' ***** '/ &
' *** '/ &
' * ')
print 1
end
So we have encountered a new format specifier, /, the 'slash', which advances I/O to the next record (or line). Also the free-format continuation character &, the 'ampersand', which means that the current line continues to the next noncomment line. Also the print statement where here print 1 has the same effect as write(*,1).
OK, but what if we wanted to carry out some kind of calculation to produce the picture? If we considered the picture to lie on a raster array where row i ran from 1 at the top to 9 at the bottom and column j ran from column 1 at the left to column 9 at the right, we might observe that the image is symmetric about i=5 and about j=5. If we considered i and j to run from -4 to 4 instead we might be able to see some patterns that enable us to take advantage of the symmetry now about the y-axis and x-axis. Accordingly we write a program that will print out the coordinates...
print"(9(1x:'(',i2,',',i2,')'))",[((i,j,j=-4,4),i=-4,4)];end
Now we have a couple of new program elements: there is an array constructor [stuff] which will create an array of the elements listed within the square brackets.
[(more_stuff,i=-4,4)] is an ac-implied-do which effectively creates a list by evaluating more_stuff sequentially for each value of i from -4 to 4, thus a list of 9 things.
[((still_more_stuff,j=-4,4),i=-4,4)] is a nested ac-impied-do which for each value of i makes a list by evaluating still_more_stuff sequentially for each value of j from -4 to 4, thus there is a list of 9*9=81 things.
Since still_more_stuff is i,j, i.e. 2 things, the array constructor creates an array of 162 things, each (i,j) pair with j varying faster than I.
The print statement has a format string surrounded by " double quotes rather than ' apostrophes so that we can use apostrophe-delimited strings in the format.
The 9(stuff) part is a repeat count that means to do the formats specified in stuff 9 times over.
The 1x format says just skip one space and the following colon just separates it from the next format item. We can use , (comma), : (colon), or / (slash) to separate format items. As the reader will recall, slash skips to the next record; for the purposes or the current discussion let's ignore the distinction between comma and colon.
The i2 format prints out an integer in a field of width 2. If it takes more than 2 characters to print out the integer it will print out two asterisks ** instead.
So the format with the repeat count will print out 2*9=18 integers. When the format is exhausted there are rules called format reversion that in this case will result in output advancing to the next line and the format being reused.
Finally, in free format code one can write the next line of code on the current one if the current statement is followed by a semicolon ;. Thus ;end puts the required end statement at the end of the program. Note that the introductory program statement, although good style, is optional.
The output of the program is as follows:
(-4,-4) (-4,-3) (-4,-2) (-4,-1) (-4, 0) (-4, 1) (-4, 2) (-4, 3) (-4, 4)
(-3,-4) (-3,-3) (-3,-2) (-3,-1) (-3, 0) (-3, 1) (-3, 2) (-3, 3) (-3, 4)
(-2,-4) (-2,-3) (-2,-2) (-2,-1) (-2, 0) (-2, 1) (-2, 2) (-2, 3) (-2, 4)
(-1,-4) (-1,-3) (-1,-2) (-1,-1) (-1, 0) (-1, 1) (-1, 2) (-1, 3) (-1, 4)
( 0,-4) ( 0,-3) ( 0,-2) ( 0,-1) ( 0, 0) ( 0, 1) ( 0, 2) ( 0, 3) ( 0, 4)
( 1,-4) ( 1,-3) ( 1,-2) ( 1,-1) ( 1, 0) ( 1, 1) ( 1, 2) ( 1, 3) ( 1, 4)
( 2,-4) ( 2,-3) ( 2,-2) ( 2,-1) ( 2, 0) ( 2, 1) ( 2, 2) ( 2, 3) ( 2, 4)
( 3,-4) ( 3,-3) ( 3,-2) ( 3,-1) ( 3, 0) ( 3, 1) ( 3, 2) ( 3, 3) ( 3, 4)
( 4,-4) ( 4,-3) ( 4,-2) ( 4,-1) ( 4, 0) ( 4, 1) ( 4, 2) ( 4, 3) ( 4, 4)
Looking at these results we might observe that within the diamond, |i|+|j|<=4 while outside, |i|+|j|>=5. Let's create a program to check this:
print'(9(L1))',[((abs(j)+abs(i)<5,j=-4,4),i=-4,4)];end
Similar to the last program, but now the still_more_stuff in the inner ac-implied-do, abs(j)+abs(i)<5 is a logical expression which asks 'is |j|+|i| less than 5?' The value of the expression will be .TRUE. or .FALSE., depending on the outcome of this test.
The L1 format is a logical I/O specifier that outputs T for .TRUE. or F for .FALSE..
Output of the program is as follows:
FFFFTFFFF
FFFTTTFFF
FFTTTTTFF
FTTTTTTTF
TTTTTTTTT
FTTTTTTTF
FFTTTTTFF
FFFTTTFFF
FFFFTFFFF
We can see the diamond but we need to convert to (spaces) and * (asterisks):
print'(9a)',merge('*',' ',[((abs(j)+abs(i)<5,j=-4,4),i=-4,4)]);end
And this does it! The merge function processes our logical array (the third argument) and everywhere a .TRUE. element is encountered, replaces it with an asterisk * (the first argument) while every .FALSE. element is replaced by a space (the second argument).
The resulting 81-element character array is printed out 9 elements at a time by the (9a) format string, resulting in the desired output. The whole program, although complex to write, was only 66 characters long :)

I propose this approach on implementation, because it gives you flexibility on the character string length to be printed.
program chardesign
implicit none
call print_diamond('*', 5, 1)
call print_diamond('()', 3, 3)
call print_diamond('.', 1, 4)
call print_diamond('0', 0, 3)
contains
subroutine print_diamond(str, depth, start)
character(*), intent(in) :: str
integer, intent(in) :: depth, start
character(len(str)) :: spc
integer :: i, span
spc = ''
span = start + (depth - 1) * 2
print '(a)', (repeat(spc, (span - i) / 2) // repeat(str, i), i = start, span, 2)
print '(a)', (repeat(spc, (span - i) / 2) // repeat(str, i), i = span - 2, start, -2)
end
end
This yields the following output:
*
***
*****
*******
*********
*******
*****
***
*
()()()
()()()()()
()()()()()()()
()()()()()
()()()
....

Related

Need help implementing a certain logic that will fill a text to a certain width.

The task is to justify text within a certain width.
user inputs: Hello my name is Harrry. This is a sample text input that nobody
will enter.
output: What text width do you want?
user inputs: 15
output: |Hello my name|
|is Harrry. This|
|is a sample|
|text that|
|nobody will|
|enter. |
Basically, the line has to be 15 spaces wide including blank spaces. Also, if the next word in the line cant fit into 15, it will skip entirely. If there are multiple words in a line, it will try to distribute the spaces evenly between each word. See the line that says "Is a sample" for example.
I created a vector using getline(...) and all that and the entire text is saved in a vector. However, I'm kind of stuck on moving forward. I tried using multiple for loops, but I just cant seem to skip lines or even out the spacing at all.
Again, not looking or expecting anyone to solve this, but I'd appreciate it if you could guide me into the right direction in terms of logic/algorithm i should think about.
You should consider this Dynamic programming solution.
Split text into “good” lines
Since we don't know where we need to break the line for good justification, we start guessing where the break to be done to the paragraph. (That is we guess to determine whether we should break between two words and make the second word as start of the next line).
You notice something? We brutefore!
And note that if we can't find a word small enought to fit in the remaining space in the current line, we insert spaces inbetween the words in the current line. So, the space in the current line depends on the words that might go into the next or previous line. That's Dependency!
You are bruteforcing and you have dependency,there comes the DP!
Now lets define a state to identify the position on our path to solve this problem.
State: [i : j] ,which denotes line of words from ith word to jth word in the original sequence of words given as input.
Now, that you have state for the problem let us try to define how these states are related.
Since all our sub-problem states are just a pile of words, we can't just compare the words in each state and determine which one is better. Here better delineates to the use of line's width to hold maximum character and minimum spaces between the words in the particular line. So, we define a parameter, that would measure the goodness of the list of words from ith to jth words to make a line. (recall our definition of subproblem state). This is basically evaluating each of our subproblem state.
A simple comparison factor would be :
Define badness(i, j) for line of words[i : j].
For example,
Infinity if total length > page width,
else (page width − total length of words in current line)3
To make things even simple consider only suffix of the given text and apply this algorithm. This would reduce the DP table size from N*N to N.
So, For finishing lets make it clear what we want in DP terms,
subproblem = min. badness for suffix words[i :]
=⇒ No.of subproblems = Θ(n) where n = no of words
guessing = where to end first line, say i : j
=⇒ no. of choices for j = n − i = O(n)
recurrence relation between the subproblem:
• DP[i] = min(badness (i, j) + DP[j] for j in range (i + 1, n + 1))
• DP[n] = 0
=⇒ time per subproblem = Θ(n)
so, total time = Θ(n^2).
Also, I'll leave it to you how insert spaces between words after determining the words in each line.
Logic would be:
1) Put words in array
2) Loop though array of words
3) Count the number of chars in each word, and check until they are the text width or less (skip if more than textwidth). Remember the number of words that make up the total before going over 15 (example remember it took 3 words to get 9 characters, leaving space for 6 spaces)
4) Divide the number of spaces required by (number of words - 1)
5) Write those words, writing the same number of spaces each time.
Should give the desired effect I hope.
You obviously have some idea how to solve this, as you have already produced the sample output.
Perhaps re-solve your original problem writing down in words what you do in each step....
e.g.
Print text asking for sentence.
Take input
Split input into words.
Print text asking for width.
...
If you are stuck at any level, then expand the details into sub-steps.
I would look to separate the problem of working out a sequence of words which will fit onto a line.
Then how many spaces to add between each of the words.
Below is an example for printing one line after you find how many words to print and what is the starting word of the line.
std::cout << "|";
numOfSpaces = lineWidth - numOfCharsUsedByWords;
/*
* If we have three words |word1 word2 word3| in a line
* ideally the spaces to print between then are 1 less than the words
*/
int spaceChunks = numOfWordsInLine - 1;
/*
* Print the words from starting point to num of words
* you can print in a line
*/
for (j = 0; j < numOfWordsInLine; ++j) {
/*
* Calculation for the number of spaces to print
* after every word
*/
int spacesToPrint = 0;
if (spaceChunks <= 1) {
/*
* if one/two words then one
* chunk of spaces between so fill then up
*/
spacesToPrint = numOfSpaces;
} else {
/*
* Here its just segmenting a number into chunks
* example: segment 7 into 3 parts, will become 3 + 2 + 2
* 7 to 3 = (7%3) + (7/3) = 1 + 2 = 3
* 4 to 2 = (4%2) + (4/2) = 0 + 2 = 2
* 2 to 1 = (2%1) + (2/1) = 0 + 2 = 2
*/
spacesToPrint = (numOfSpaces % spaceChunks) + (numOfSpaces / spaceChunks);
}
numOfSpaces -= spacesToPrint;
spaceChunks--;
cout << words[j + lineStartIdx];
for (int space = 0; space < spacesToPrint; space++) {
std::cout << " ";
}
}
std::cout << "|" << std::endl;
Hope this code helps. Also you need to consider what happens if you set width less then the max word size.

code debugging: 'take a list of ints between 0-9, return largest number divisible by 3'

I'm trying to understand what is wrong with my current solution.
The problem is as follows:
using python 2.7.6"
You have L, a list containing some digits (0 to 9). Write a function answer(L) which finds the largest number that can be made from some or all of these digits and is divisible by 3. if it is not possible to make such a number, return 0 as the answer. L will contain anywhere from 1 to 9 digits. The same digit may appear multiple times in the list, but each element in the list may only be used once.
input: (int list) l = [3, 1, 4, 1]
output: (int) 4311
input (int list) l = [3 ,1 ,4 ,1 ,5, 9]
output: (int) = 94311
This is my code to tackle the problem:
import itertools
def answer(l):
'#remove the zeros to speed combinatorial analysis:'
zero_count = l.count(0)
for i in range(l.count(0)):
l.pop(l.index(0))
' # to check if a number is divisible by three, check if the sum '
' # of the individual integers that make up the number is divisible '
' # by three. (e.g. 431: 4+3+1 = 8, 8 % 3 != 0, thus 431 % 3 != 0)'
b = len(l)
while b > 0:
combo = itertools.combinations(l, b)
for thing in combo:
'# if number is divisible by 3, reverse sort it and tack on zeros left behind'
if sum(thing) % 3 == 0:
thing = sorted(thing, reverse = True)
max_div_3 = ''
for digit in thing:
max_div_3 += str(digit)
max_div_3 += '0'* zero_count
return int(max_div_3)
b -= 1
return int(0)
I have tested this assignment many times in my own sandbox and it always works.
However when I have submitted it against my instructor, I end up always failing 1 case.. with no explanation of why. I cannot interrogate the instructor's tests, they are blindly pitched against the code.
Does anyone have an idea of a condition under which my code fails to either return the largest integer divisible by 3 or, if none exists, 0?
The list always has at least one number in it.
It turns out that the problem was with the order of itertools.combinations(l, b)
and sorted(thing, reverse = True). The original code was finding the first match of n%3 == 0 but not necessarily the largest match. Performing sort BEFORE itertools.combinations allowed itertools to find the largest n%3 == 0.

Scala: decrement for-loop

I noticed that the following two for-loop cases behave differently sometimes while most of the time they are the same. I couldn't figure out the pattern, does anyone have any idea? Thanks!
case 1:
for (i <- myList.length - 1 to 0 by -1) { ... }
case 2:
for (i <- myList.length - 1 to 0) { ...}
Well, they definitely don't do the same things. n to 0 by -1 means "start at n and go to 0, counting backwards by 1. So:
5 to 0 by -1
// res0: scala.collection.immutable.Range = Range(5, 4, 3, 2, 1, 0)
Whereas n to 0 means "start at n and got to 0 counting forward by 1". But you'll notice that if n > 0, then there will be nothing in that list, since there is no way to count forward to 0 from anything greater than zero.
5 to 0
// res1: scala.collection.immutable.Range.Inclusive = Range()
The only way that they would produce the same result is if n=0 since counting from 0 to 0 is the same forwards and backwards:
0 to 0 by -1 // Range(0)
0 to 0 // Range(0)
In your case, since you're starting at myList.length - 1, they will produce the same result when the length of myList is 1.
In summary, the first version makes sense, because you want to count down to 0 by counting backward (by -1). And the second version doesn't make sense because you're not going to want to count forward to 0 from a length (which is necessarily non-negative).
First, we need to learn more about how value members to and by works.
to - Click Here for API documentation
to is a value member that appears in classes like int, double etc.
scala> 1 to 3
res35: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
Honestly, you don't have to use start to end by step and start.to(end, step) will also work if you are more comfortable working with in this world. Basically, to will return you a Range.Inclusive object if we are talking about integer inputs.
by - Click Here for API documentation
Create a new range with the start and end values of this range and a new step
scala> Range(1,8) by 3
res54: scala.collection.immutable.Range = Range(1, 4, 7)
scala> Range(1,8).by(3)
res55: scala.collection.immutable.Range = Range(1, 4, 7)
In the end, lets spend some time looking at what happens when the step is on a different direction from start to end. Like 1 to 3 by -1
Here is the source code of the Range class and it is actually pretty straightforward to read:
def by(step: Int): Range = copy(start, end, step)
So by is actually calling a function copy, so what is copy?
protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step)
So copy is literally recreate a new range with different step, then lets look at the constructor or Range itself.
Reading this paragraph of code
override final val isEmpty = (
(start > end && step > 0)
|| (start < end && step < 0)
|| (start == end && !isInclusive)
)
These cases will trigger the exception and your result will be a empty Range in cases like 1 to 3 by -1..etc.
Sorry the length of my post is getting out of control since I am also learning Scala now.
Why don't you just read the source code of Range, it is written by Martin Odersky and it is only 500 lines including comments :)

Skipping empty lines in Fortran

I'm working with a fortran code, where my input file looks something like this:
...
Binning n: 4, "Si2-Events", Event #: 12, Primary(s) weight 1.0000E+00
Number of hit cells: 3
488534 4.23038400E-05 489533 1.50734719E-04 489534 5.79968946E-05
Binning n: 4, "Si2-Events", Event #: 13, Primary(s) weight 1.0000E+00
Number of hit cells: 2
477500 3.04398331E-04 478500 1.13192732E-06
Binning n: 4, "Si2-Events", Event #: 14, Primary(s) weight 1.0000E+00
Number of hit cells: 2
512496 1.32522946E-05 513496 2.86743394E-04
Binning n: 4, "Si2-Events", Event #: 15, Primary(s) weight 1.0000E+00
Number of hit cells: 2
476539 1.95245666E-04 476540 2.37216373E-05
Binning n: 4, "Si2-Events", Event #: 16, Primary(s) weight 1.0000E+00
Number of hit cells: 9
502533 1.26090490E-05 502534 1.00212252E-04 503527 3.07000097E-04 503528 9.53662311E-06 503529 9.42530642E-06 503530 1.07992764E-05 503531 1.26466557E-05 503532 1.68176994E-05 503533 1.18242851E-05
...
In other words, I have a file with many many lines, each displaying a cell number and energy in the third row, e.g.
488534 4.23038400E-05 489533 1.50734719E-04 489534 5.79968946E-05
I want to write a fortran code that reads only this line, and writes to an output file the cell number and energy in two colums, something like
Line 1
Cells 488534
489533
489534
Energy
4.23038400E-05
1.50734719E-04
5.79968946E-05
Line 2
Cells 477500
478500
Energy 3.04398331E-04
1.13192732E-06
etc...
The problem is that the number of cells varies from line to line.
How can I make it skip to the next line when it has read all the values?
Here is a little bit of the code I tested out:
open (unit=7, file="Si1.txt", action="read", access="sequential")
open (unit=8, file="output.txt", action="write")
do i = 1, 900
read (7,*) line1
read (7,*) line2
read (7,*) cell1, energy1, cell2, energy2
write(8,*) "Run = ", i, "and cells = ", cell1, cell2, "and energy = ", energy1, energy2
end do
Problem is that this only worked as long as there was two or more values in that row, and not if it was less than two.
I'm a bit lost (and possibly a noob here), but any suggestions on how to make this work?
You're currently ignoring the useful information on the 2nd line of each block, ie the number of cell number/energy pairs to be found on the 3rd line of the block. So get that information.
Replace your
read(7,*) line2
by a statement such as
read(7,'(a32,i)') words, num_cells
I write 'such as' because I haven't counted how many characters to read into the words variable (which you will have declared as character(len=32) :: words or similar), you'll have to do that for yourself. Following execution of this statement the integer variable num_cells will have the number of cell pairs to read from the next line. Replace your
read (7,*) cell1, energy1, cell2, energy2
with
do ix = 1, num_cells
read (7,fmt=*, advance='no') cell(ix), energy(ix)
end do
read (7, '()', advance = ’yes’)
The advance=no argument tells the processor not to move to the next line in the input file after reading the cell/energy pair. The line at the end of the loop, on the other hand, tells the processor to move to the next line.
Obviously (?) I haven't written you a complete solution but you should be able to take it the rest of the way. And I haven't tested this for you, so there may well be minor errors with the syntax.

Creating a histogram with C++ (Homework)

In my c++ class, we got assigned pairs. Normally I can come up with an effective algorithm quite easily, this time I cannot figure out how to do this to save my life.
What I am looking for is someone to explain an algorithm (or just give me tips on what would work) in order to get this done. I'm still at the planning stage and want to get this code done on my own in order to learn. I just need a little help to get there.
We have to create histograms based on a 4 or 5 integer input. It is supposed to look something like this:
Calling histo(5, 4, 6, 2) should produce output that appears like:
*
* *
* * *
* * *
* * * *
* * * *
-------
A B C D
The formatting to this is just killing me. What makes it worse is that we cannot use any type of arrays or "advanced" sorting systems using other libraries.
At first I thought I could arrange the values from highest to lowest order. But then I realized I did not know how to do this without using the sort function and I was not sure how to go on from there.
Kudos for anyone who could help me get started on this assignment. :)
Try something along the lines of this:
Determine the largest number in the histogram
Using a loop like this to construct the histogram:
for(int i = largest; i >= 1; i--)
Inside the body of the loop, do steps 3 to 5 inclusive
If i <= value_of_column_a then print a *, otherwise print a space
Repeat step 3 for each column (or write a loop...)
Print a newline character
Print the horizontal line using -
Print the column labels
Maybe i'm mistaken on your q, but if you know how many items are in each column, it should be pretty easy to print them like your example:
Step 1: Find the Max of the numbers, store in variable, assign to column.
Step 2: Print spaces until you get to column with the max. Print star. Print remaining stars / spaces. Add a \n character.
Step 3: Find next max. Print stars in columns where the max is >= the max, otherwise print a space. Add newline. at end.
Step 4: Repeat step 3 (until stop condition below)
when you've printed the # of stars equal to the largest max, you've printed all of them.
Step 5: add the -------- line, and a \n
Step 6: add row headers and a \n
If I understood the problem correctly I think the problem can be solved like this:
a= <array of the numbers entered>
T=<number of numbers entered> = length(a) //This variable is used to
//determine if we have finished
//and it will change its value
Alph={A,B,C,D,E,F,G,..., Z} //A constant array containing the alphabet
//We will use it to print the bottom row
for (i=1 to T) {print Alph[i]+" "}; //Prints the letters (plus space),
//one for each number entered
for (i=1 to T) {print "--"}; //Prints the two dashes per letter above
//the letters, one for each
while (T!=0) do {
for (i=1 to N) do {
if (a[i]>0) {print "*"; a[i]--;} else {print " "; T--;};
};
if (T!=0) {T=N};
}
What this does is, for each non-zero entered number, it will print a * and then decrease the number entered. When one of the numbers becomes zero it stops putting *s for its column. When all numbers have become zero (notice that this will occur when the value of T comes out of the for as zero. This is what the variable T is for) then it stops.
I think the problem wasn't really about histograms. Notice it also doesn't require sorting or even knowing the