In Haskell, we can use an infix operator as a parameter name, e.g.:
f :: (Int -> Int -> Int) -> Int
f (|+|) = 3 |+| 4
Is it possible to do something similar in Idris 2? I tried the following:
f : (Int -> Int -> Int) -> Int
f (|+|) = 3 |+| 4
But it fails with:
Unknown operator '|+|'
slice:2:11--2:18
1 | f : (Int -> Int -> Int) -> Int
2 | f (|+|) = 3 |+| 5
^^^^^^^
This question already has answers here:
How can I pass a reference to a stack variable to a thread?
(1 answer)
How can I sum up using concurrency from 1 to 1000000 with Rust?
(1 answer)
Closed 3 years ago.
I have an array of strings. I would like to count the total chars but using threads for parallelisation (the original problem is not this but is similar).
use std::thread;
pub fn frequency<'a>(input: &'a [&'a str], worker_count: usize) -> usize {
let handlers: Vec<thread::JoinHandle<usize>> = input
.chunks(worker_count)
.map(|chunk| thread::spawn(calculate(chunk)))
.collect();
let hashes = handlers.into_iter().map(|handler| handler.join().unwrap());
let mut sum = 0;
for h in hashes {
sum += h
}
sum
}
fn calculate<'a>(input: &'a [&'a str]) -> impl Fn() -> usize + 'a {
move || input.iter().map(|s| s.len()).sum()
}
The compiler tells me this:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:5:10
|
5 | .chunks(worker_count)
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 3:18...
--> src/lib.rs:3:18
|
3 | pub fn frequency<'a>(input: &'a [&'a str], worker_count: usize) -> usize {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:4:52
|
4 | let handlers: Vec<thread::JoinHandle<usize>> = input
| ^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `impl std::ops::Fn<()>` will meet its required lifetime bounds
--> src/lib.rs:6:22
|
6 | .map(|chunk| thread::spawn(calculate(chunk)))
| ^^^^^^^^^^^^^
I've tried to remove all lifetimes, use different lifetimes for str and the slice, and explicitly invoke calculate::<'a> but none of those solutions compile.
The input lifetime is the same everywhere: frequency declares 'a that is used in calculate, so the closure is bound to 'a because the captured variables live for 'a.
Where am I wrong?
NB: I would like not to use 'static.
Guile accepts the following code:
(use-modules (system foreign))
(define ptr (make-c-struct (list int int) '(300 43)))
However, it throws an error when the second line is replaced by:
(define ptr (make-c-struct '(int int) '(300 43)))
Is someone be able to infer what the issue could be?
$ guile --version
guile (GNU Guile) 2.0.13
$ uname -a
Linux <host> 4.8.0-1-amd64 #1 SMP Debian 4.8.5-1 (2016-10-28) x86_64 GNU/Linux
Backtrace:
In ice-9/boot-9.scm:
160: 8 [catch #t #<catch-closure 55b8628b8600> ...]
In unknown file:
?: 7 [apply-smob/1 #<catch-closure 55b8628b8600>]
In ice-9/boot-9.scm:
66: 6 [call-with-prompt prompt0 ...]
In ice-9/eval.scm:
432: 5 [eval # #]
In ice-9/boot-9.scm:
2404: 4 [save-module-excursion #<procedure 55b8628d89c0 at ice-9/boot-9.scm:4051:3 ()>]
4058: 3 [#<procedure 55b8628d89c0 at ice-9/boot-9.scm:4051:3 ()>]
In /home/<user>/path/tofile.scm:
7: 2 [#<procedure 55b862cf46c0 ()>]
In system/foreign.scm:
158: 1 [make-c-struct (int int) (300 43)]
In unknown file:
?: 0 [sizeof (int int)]
ERROR: In procedure sizeof:
ERROR: In procedure alignof: Wrong type argument in position 1: int
This:
(list int int)
Creates a list with the previously defined int value as elements, whereas this:
'(int int)
Creates a list with two symbols as elements, they're not equivalent, remember that a single quote is a shorthand for (quote (int int)), not for (list int int).
Problem Statement:
There is a broken calculator. Only a few of the digits [0 to 9] and operators [+, -, *, /] are working.
A req no. needs to be formed using the working digits and the operators. Each press on the keyboard is called an operation.
= operator is always working and is used when the req no. is formed using operators.
-1 needs to be printed in case the req no. cannot be formed using the digits and the operators provided OR exceeds the max no. of operations allowed.
At no point in time during the calculation of the result, the no. should become negative or exceed 999 [0 <= calcno <= 999]
Input:
1st line contains 3 space separated nos: no. of working digits, no. of working operators, max. no of operations allowed.
2nd line contains space separated working digits.
3rd line contains space separated working operators [1 represents +, 2 represents -, 3 represents *, 4 represents /].
4th line contains the req. no to be formed.
Output:
Find the minimum required operations to form the req no.
Example:
Input 1:
2 1 8
2 5
3
50
Possible ways:
Case 1: 2*5*5 = -> 6 operations
Case 2: 2*25 = -> 4 operations
4 is the req Answer
Input 2:
3 4 8
5 4 2
3 2 4 1
42
Possible ways:
Case 1: 42 -> 2 operations (direct key in)
Case 2: 5*4*2+2 = -> 8 operations
..........some other ways
2 is the req Answer
I am not getting a proper approach to this problem.
Can someone suggest some ways to approach the problem.
Giving some more context what vish4071 said in the comments.
Set up a graph in the following way:
Starting the graph with a root, and than the new node are the number you're aloud to use (for the example this is 2 and 5). And build up the graph level by level.
Make each level in the following way, a new node will consist either of adding number or a operator which you're aloud to use. After each operator there cannot be another operator.
If the node has a higher value than the Target value, than kill the node (target as end note), this only works for this example (if the operators are * and +). If you would be able to use the - and / operator this is not vallid.
Do this till you find the required value, and the level (+1, due to the = operation) is you're answer.
And example of the graph is given below
for your first example:
D=0 D=1
5
/
Root /
\
\2
D=1 D=2 d=3 d=4
--2
/
/
(*)___5 --> reaches answer but at level 6
/
/ (*)___2 --> complete
/ / \ 5
/ /
2 /____25_252 --> end node
\ \
\ \
\
\ 225 --> end node
\ /
22__222 --> end node
\
(*)
This is slightly better than brute forcing, maybe there is a more optimal way.
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int n,m,o;
cin>>n>>m>>o;
int arr[n];
queue<pair<int,int>> q;
for(int i=0;i<n;i++)
{
cin>>arr[i];
q.push(make_pair(arr[i],1));
}
int op[m];
for(int i=0;i<m;i++) cin>>op[i];
unordered_map<int,int> mp;
for(int i=0;i<m;i++) mp[op[i]]=1;
int target;
cin>>target;
int ans=INT_MAX;
while(!q.empty())
{
int num=q.front().first;
int count=q.front().second;
if(num==target) ans=min(ans,count);
q.pop();
for(int i=0;i<=4;i++)
{
for(int j=0;j<n;j++)
{
if(i==0 and count+1<=o)
{
q.push(make_pair(num*10+arr[j],count+1));
}
else
{
if(i==1 and mp.find(i)!=mp.end() and count+3<=o)
{
q.push(make_pair(num+arr[j],count+3));
}
if(i==2 and mp.find(i)!=mp.end() and count+3<=o)
{
q.push(make_pair(abs(num-arr[j]),count+3));
}
if(i==3 and mp.find(i)!=mp.end() and count+3<=o)
{
q.push(make_pair(num*arr[j],count+3));
}
if(i==4 and mp.find(i)!=mp.end() and count+3<=o)
{
q.push(make_pair(num/arr[j],count+3));
}
}
}
}
}
if(ans==INT_MAX) cout<<"-1"<<endl;
else cout<<ans<<endl;
return 0;
}
I have below merge sort program in algorithms book, it is mentioned that The main problem is that merging two sorted lists requires linear extra memory, and the additional work spent copying to the temporary array and back, throughout the algorithm, has the effect of slowing down the sort considerably. This copying can be avoided by judiciously switching the roles of "a" and "tmp_array" at alternate levels of the recursion.
My question is what does author mean "copying can be avoided by judiciously switching the roles of a and tmp_array at alternate levels of the recursion" and how it is possible in following code? Request to show an example how we can achieve this?
void mergesort( input_type a[], unsigned int n ) {
input_type *tmp_array;
tmp_array = (input_type *) malloc( (n+1) * sizeof (input_type) );
m_sort( a, tmp_array, 1, n );
free( tmp_array );
}
void m_sort( input_type a[], input_type tmp_array[ ], int left, int right ) {
int center;
if( left < right ) {
center = (left + right) / 2;
m_sort( a, tmp_array, left, center );
m_sort( a, tmp_array, center+1, right );
merge( a, tmp_array, left, center+1, right );
}
}
void merge( input_type a[ ], input_type tmp_array[ ], int l_pos, int r_pos, int right_end ) {
int i, left_end, num_elements, tmp_pos;
left_end = r_pos - 1;
tmp_pos = l_pos;
num_elements = right_end - l_pos + 1;
/* main loop */
while( ( 1_pos <= left_end ) && ( r_pos <= right_end ) )
if( a[1_pos] <= a[r_pos] )
tmp_array[tmp_pos++] = a[l_pos++];
else
tmp_array[tmp_pos++] = a[r_pos++];
while( l_pos <= left_end ) /* copy rest of first half */
tmp_array[tmp_pos++] = a[l_pos++];
while( r_pos <= right_end ) /* copy rest of second half */
tmp_array[tmp_pos++] = a[r_pos++];
/* copy tmp_array back */
for(i=1; i <= num_elements; i++, right_end-- )
a[right_end] = tmp_array[right_end];
}
I'm going to assume that, without looking at this code, it is performing merge sort by declaring a contiguous block of memory the same size as the original.
So normally merge sort is like this:
split array in half
sort half-arrays by recursively invoking MergeSort on them
merge half-arrays back
I'm assuming it's recursive, so no copies will be done before we're sorting sub-arrays of size 2. Now what happens?
_ means it is memory we have available, but we don't care about the data in it
original:
8 5 2 3 1 7 4 6
_ _ _ _ _ _ _ _
Begin recursive calls:
recursive call 1:
(8 5 2 3) (1 7 4 6)
_ _ _ _ _ _ _ _
recursive call 2:
((8 5) (2 3)) ((1 7) (4 6))
_ _ _ _ _ _ _ _
recursive call 3:
(((8) (5))((2) (3)))(((1) (7))((4) (6)))
_ _ _ _ _ _ _ _
Recursive calls resolving with merging, PLUS COPYING (uses more memory, or alternatively is 'slower'):
merge for call 3, using temp space:
(((8) (5))((2) (3)))(((1) (7))((4) (6))) --\ perform merge
(( 5 8 )( 2 3 ))(( 1 7 )( 4 6 )) <--/ operation
UNNECESSARY: copy back:
(( 5 8 )( 2 3 ))(( 1 7 )( 4 6 )) <--\ copy and
_ _ _ _ _ _ _ _ --/ ignore old
merge for call 2, using temp space:
(( 5 8 )( 2 3 ))(( 1 7 )( 4 6 )) --\ perform merge
( 2 3 5 8 )( 1 4 6 7 ) <--/ operation
UNNECESSARY: copy back:
( 2 3 5 8 )( 1 4 6 7 ) <--\ copy and
_ _ _ _ _ _ _ _ --/ ignore old
merge for call 1, using temp space:
( 2 3 5 8 )( 1 4 6 7 ) --\ perform merge
1 2 3 4 5 6 7 8 <--/ operation
UNNECESSARY: copy back:
1 2 3 4 5 6 7 8 <--\ copy and
_ _ _ _ _ _ _ _ --/ ignore old
What the author is suggesting
Recursive calls resolving with merging, WITHOUT COPYING (uses less memory):
merge for call 3, using temp space:
(((8) (5))((2) (3)))(((1) (7))((4) (6))) --\ perform merge
(( 5 8 )( 2 3 ))(( 1 7 )( 4 6 )) <--/ operation
merge for call 2, using old array as temp space:
( 2 3 5 8 )( 1 4 6 7 ) <--\ perform merge
(( 5 8 )( 2 3 ))(( 1 7 )( 4 6 )) --/ operation (backwards)
merge for call 1, using temp space:
( 2 3 5 8 )( 1 4 6 7 ) --\ perform merge
1 2 3 4 5 6 7 8 <--/ operation
There you go: you don't need to do copies as long as you perform each "level" of the merge-sort tree in lock-step, as shown above.
You may have a minor issue of parity, also as demonstrated above. That is, your result may be in your temp_array. You either have three options for dealing with this:
returning the temp_array as the answer, and release the old memory (if your application is fine with that)
perform a single array copy operation, to copy temp_array back into your original array
allow yourself to consume a mere twice-as-much memory, and perform a single cycle of merges from temp_array1 to temp_array2 then back to original_array, then release temp_array2. The parity issue should be resolved.
This is not necessarily "faster":
additional work spent copying to the temporary array and back
This is actually not the core reason why it's 'faster' per se. It is obviously not asymptotically faster, nor necessarily even faster. There is a notion of latency vs. throughput. Generally running time is measured in latency, because extra garbage work (like releasing memory) may be done asynchronously. You don't necessarily need to copy "back" to the original array depending on your language. However, if you are repeating something many times on memory-bound hardware in a garbage-collected language, the garbage collection can occasionally be forced to spike if the GC algorithm is a poor choice for what you are doing (or if this is C, maybe you are waiting to allocate). Thus if you were to create extra memory in a GC language, it should not really count against you. Granted, this may cause you not to take advantage of cache properly if you use too much memory. You'd have to benchmark it yourself, very carefully for your use case.
I do not recommend creating random temporary arrays for each step though, as that would make memory O(N log(N)) and this is a trivial optimization.
Minor notes on in-placeness:
Also, the reason you can't naively do it in-place is because while you are merging two sorted sub-arrays, the new result sorted sub-array may take arbitrarily many from one input array before spontaneously swap to the other array. For example, as you can see we need a buffer because our input arrays might get split into fragments:
( 4 6 7 8 10)(1 2 3 5 9 11)(... other sub-arrays)
( 1)(6 7 8 10)(4)(2 3 5 9 11)(...
( 1 2)(7 8 10)(4 6)(3 5 9 11) ...
( 1 2 3)(8 10)(4 6 7)(5 9 11)
( 1 2 3 4(10)(8)(6 7)(5 9 11) ooph :-(
( 1 2 3 4 5)(8)(6 7)(10)(9 11) ooph
You might be able to so cleverly in-place if you do some weird variant of the kth-statistic median-of-medians algorithm, performing your merge into the middle of the two arrays rather than the start (merging from a specifically chosen element outwards left/decreasing and right/increasing simultaneously). I'm not sure how one would implement that though, or if the hunch is true.
(very minor note: Perhaps those who are familiar with sorting algorithms should be careful of comparing a traditional swap traditional swap operation involving a tmp variable in a register, which is two reads-from-cache and two writes-to-cache, to not-in-place copying to other bits of memory, without a per-operation counting argument.)
Certainly, OP's method is extremely simple to code for only twice as much memory.
Start by thinking of merge sort in this way.
0: Consider the input array A0 as a collection of ordered sequences of
length 1.
1: Merge each consecutive pair of sequences from A0, constructing a
new temporary array A1.
2: Merge each consecutive pair of sequences from A1, constructing a
new temporary array A2.
...
Finish when the last iteration results in a single sequence.
Now, you can obviously get away with just a single temporary array by doing this:
0: Consider the input array A0 as a collection of ordered sequences of
length 1.
1: Merge each consecutive pair of sequences from A0, constructing a
new temporary array A1.
2: Merge each consecutive pair of sequences from A1, overwriting A0
with the result.
3: Merge each consecutive pair of sequences from A0, overwriting A1
with the result.
...
Finish when the last iteration results in a single sequence.
Of course, you can be even smarter than this. If you want to be nicer to the cache, you might decide to sort top-down, rather than bottom-up. In this case, it hopefully becomes obvious what your textbook means when it refers to tracking the role of the arrays at different levels of recursion.
Hope this helps.
Here is my implementation without extra copies.
public static void sort(ArrayList<Integer> input) {
mergeSort(input, 0, input.size() - 1);
}
/**
* Sorts input and returns inversions number
* using classical divide and conquer approach
*
* #param input Input array
* #param start Start index
* #param end End index
* #return int
*/
private static long mergeSort(ArrayList<Integer> input, int start, int end) {
if (end - start < 1) {
return 0;
}
long inversionsNumber = 0;
// 1. divide input into subtasks
int pivot = start + (int) Math.ceil((end - start) / 2);
if (end - start > 1) {
inversionsNumber += mergeSort(input, start, pivot);
inversionsNumber += mergeSort(input, pivot + 1, end);
}
// 2. Merge the results
int offset = 0;
int leftIndex = start;
int rightIndex = pivot + 1;
while (leftIndex <= pivot && rightIndex <= end) {
if (input.get(leftIndex + offset) <= input.get(rightIndex)) {
if (leftIndex < pivot) {
leftIndex++;
} else {
rightIndex++;
}
continue;
}
moveElement(input, rightIndex, leftIndex + offset);
inversionsNumber += rightIndex - leftIndex - offset;
rightIndex++;
offset++;
}
return inversionsNumber;
}
private static void moveElement(ArrayList<Integer> input, int from, int to) {
assert 0 <= to;
assert to < from;
assert from < input.size();
int temp = input.get(from);
for (int i = from; i > to; i--) {
input.set(i, input.get(i - 1));
}
input.set(to, temp);
}
Look at the very last part of the merge function. What if, instead of copying that data, you just used the knowledge that the sorted part is now in tmp_array instead of a when the function returns, and a is available for use as a temp.
Details are left as an exercise for the reader.