Related
How do I beam from a series of notes to a rest at the same vertical position as a rest in a way that looks appealing? Relevent snippet:
\version "2.20.0"
\new Staff {
c'16[ c' \override Rest.staff-position = #1 r ]
}
What it looks like.
I think the property you are looking for is Staff.Beam.positions, which takes a pair of numbers and sets the beam anchor points, left and right, respectively. The property Stem.length only works for non-beamed stems. I personally like to change Stem.stemlet-length to a value larger than zero when beaming from/over/to a rest, as shown in my example below. Just delete that line if that's not to your liking and lower the Beam.positions to taste.
\version "2.20.0"
\new Staff {
\override Staff.Beam.positions = #'(3.5 . 3.5)
\override Staff.Stem.stemlet-length = #0.75
c'16[
c'
\override Rest.staff-position = #1
r ]
}
Result:
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a large csv file with thousands of columns (50,000 rows and 25,000 columns).
I want to;
Obtain the list of all columns with same values
Remove all column obtained in step 1
Sample input
F1,F2,F3,F4
0,2,1,4
0,1,1,3
0,3,1,3
0,2,1,3
Sample output
Columns with same values: F1 F2
F2,F4
2,4
1,3
3,3
2,3
I have implemented python based solutions which works fine for small files but are too slow for large files (more than 8 GB).
A solution in any programming language (but robust and fast) will be appreciated.
another awk, using subset of #Luuk's sample input
$ awk -F, 'NR==FNR && NR>1 {if(NR>2) for(i=1;i<=NF;i++) if($i!=p[i]) c[i];
split($0,p); next}
FNR==1 {n=asorti(c,m); max=m[n]}
{for(i in c) printf "%s",$i (i==max?RS:FS)}' file{,}
F2,F4
1,3
2,2
0,1
2,1
2,0
1,2
1,3
The trick is it's enough to check if any of the consecutive values are different.
some extra work to find the max included column index (required for clean printing).
If you have thousands of columns you can speed up the filtering by changing i<=NF to i<=NF && !(i in c)
Perhaps this alternative will be the fastest, which quickly removes the columns if there are different values from the search set.
$ awk -F, 'NR==FNR && NR==1 {for(i=1;i<=NF;i++) a[i]; next}
NR==FNR {if(NR>2) for(i in a) if($i!=p[i]) {delete a[i]; c[i]};
split($0,p); next}
FNR==1 {n=asorti(c,m); max=m[n]}
{for(i in c) printf "%s",$i (i==max?RS:FS)}' file{,}
All solutions double scans the file so it can't be very fast but I expect it to complete in couple minutes. Please post the timings if you can test.
$ cat tst.awk
BEGIN { FS=OFS="," }
NR==FNR {
if ( NR > 1 ) {
for (inFldNr=1; inFldNr<=NF; inFldNr++) {
vals[inFldNr][$inFldNr]
}
}
next
}
FNR==1 {
for (inFldNr=1; inFldNr<=NF; inFldNr++) {
if ( length(vals[inFldNr]) > 1 ) {
out2in[++numOutFlds] = inFldNr
}
}
}
{
for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
printf "%s%s", $(out2in[outFldNr]), (outFldNr<numOutFlds ? OFS : ORS)
}
}
$ awk -f tst.awk file file
F2,F4
2,4
1,3
3,3
2,3
EDIT: tested against a file that's 50,000 lines of 25,000 fields:
$ time awk -f tst.awk file.csv file.csv > out.csv
real 17m42.591s
user 17m29.421s
sys 0m3.858s
The above input file was created by running this script:
$ awk 'BEGIN{OFS=","; x=50000; y=25000; for (i=1;i<=x;i++) for (j=1;j<=y;j++) printf "%s%s", (i>1?substr(rand(),3,1):"F"j), (j<y?OFS:ORS)}' > file.csv
$ wc file.csv
50000 50000 2500113283 file.csv
$ ls -lh file.csv
-rw-r--r-- 1 MyLogin None 2.4G Nov 22 12:45 file.csv
I created a piece of code in .NET 5.0, which has following output:
(EDIT: oops, i noticed i have compiled it for .NET 3.1 🙄)
WHICH COLUMNS HAVE UNIQUE VALUES
0: True
1: False
2: True
3: False
TIME AFTER CHECKING UNIQUE COLUMNS: 72,9047581 secs
TIME AFTER WRITING NON UNIQUE COLUMNS TO NEW FILE: 221,751107 secs
This is under 4 minutes. My PC (running Windows) might be quicker then yours, but the difference, compared to 1 hour, is to large... 😉
And i created an 'input file with 4 columns as your sample, like this:
D:\Temp>type random.txt
0,1,1,3
0,2,1,2
0,0,1,1
0,2,1,1
0,2,1,0
0,1,1,2
0,1,1,3
0,0,1,3
0,2,1,4
0,3,1,1
....
My example file has 2756616192 bytes, or 344577024 lines.
The output looks like this:
D:\Temp>type randomNEW.txt
1,3
2,2
0,1
2,1
2,0
1,2
1,3
0,3
2,4
3,1
this file has 1722885120 bytes, and has also 344577024 lines.
The source looks like this (note: I am not very experienced in C#, just learning, so there might be things that can be improved!):
using System;
using System.IO;
namespace ConsoleApp59
{
class Program
{
static void Main(string[] args)
{
DateTime start = DateTime.Now;
bool[] a = new bool[4];
int[] first = new int[4];
int t = 0;
for(int i=0; i<4; i++ ) { a[i] = true; }
foreach (string line in File.ReadLines(#"d:\temp\random.txt"))
{
string[] s = line.Split(",");
int[] b = new int[4]{ Convert.ToInt32(s[0]), Convert.ToInt32(s[1]), Convert.ToInt32(s[2]), Convert.ToInt32(s[3]) };
if (t==0)
{
first = b;
}
else
{
for (int i = 0; i < 4; i++)
{
if (a[i]) a[i] = b[i] == first[i];
}
}
t++;
}
Console.WriteLine("WHICH COLUMNS HAVE UNIQUE VALUES");
for(int i=0; i<4; i++)
{
Console.WriteLine($"{i}: {a[i]}");
}
Console.WriteLine($"TIME AFTER CHECKING UNIQUE COLUMNS: { ((DateTime.Now-start).TotalSeconds)} secs");
StreamWriter n = new StreamWriter(#"D:\temp\randomNEW.txt");
foreach (string line in File.ReadLines(#"d:\temp\random.txt"))
{
string[] s = line.Split(",");
string output = "";
for (int i=0; i<4; i++ )
{
if (!a[i]) output += String.Format($"{s[i]},");
}
if (output.EndsWith(",")) output = output.Substring(0, output.Length - 1);
output += "\r\n";
n.Write(output.ToCharArray());
}
n.Close();
Console.WriteLine($"TIME AFTER WRITING NON UNIQUE COLUMNS TO NEW FILE: { ((DateTime.Now - start).TotalSeconds)} secs");
//Console.ReadLine();
}
}
}
EDIT: I just did a test on a Mac-MINI (Late 2012; macOS Catalina 10.15.7; 2.3 Ghz; 16Gb RAM)
TIME AFTER CHECKING UNIQUE COLUMNS: 104.473532 secs
TIME AFTER WRITING NON UNIQUE COLUMNS TO NEW FILE: 300.272936 secs
I'm trying to develop a simple calculator that bends the rules of math. I want it to ignore the usual math rules and perform from right to left. The user inputs a whole string as a math problem.
For example:
input: 123 - 10 + 4 * 10
Should be solved like this:
123 - 10 + 4 * 10 = 123 - ( 10 + ( 4 * 10 ) ) = 73.
Here is what i currently have:
use strict;
use warnings;
use feature 'say';
while (<>) { # while we get input
my ($main, #ops) = reverse /[\d+\-*\/]+/g; # extract the ops
while (#ops) { # while the list is not empty
$main = calc($main, splice #ops, 0, 2); # take 2 items off the list and process
}
say $main; # print result
}
sub calc {
my %proc = (
"+" => sub { $_[0] + $_[1] },
"-" => sub { $_[0] - $_[1] },
"/" => sub { $_[0] / $_[1] },
"*" => sub { $_[0] * $_[1] }
);
return $proc{$_[1]}($_[0], $_[2]);
}
Here is what output i get:
123 - 10 + 4 * 10 = ((123 - 10) + 4) * 10 = 1170
As you can see - it solves the problem from left to right. My question is - how can i reverse this? I want it to get solved from right to left. Any help will be appreciated, thanks.
This seems to do what you want.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my #tokens = #ARGV ? #ARGV : split /\s+/, '123 - 10 + 4 * 10';
if (grep { !/^[-+*i%]$/ and /\D/ } #tokens) {
die "Invalid input: #tokens\n";
}
while (#tokens >= 3) {
my $expr = join ' ', #tokens[-3 .. -1];
splice #tokens, -3, 3, eval $expr;
}
say "#tokens";
I split the input into tokens and then process the array of tokens three elements at a time, working from the end. Each time, I replace the final three tokens with the result of evaluating the expression.
I've used eval here instead of the dispatch table calculator that you've used. You always want to be pretty sure of your input when using eval, so I've included a quick and dirty validation step as well.
Taking a page from postfix/RPN evaluation strategies, and keeping two stacks, one for operations, one for numbers, makes for a simple implementation:
#!/usr/bin/env perl
use warnings;
use strict;
use feature 'say';
{
my %proc = (
"+" => sub { $_[0] + $_[1] },
"-" => sub { $_[0] - $_[1] },
"/" => sub { $_[0] / $_[1] },
"*" => sub { $_[0] * $_[1] }
);
sub calc {
my #tokens = reverse split ' ', $_[0];
my #opstack = grep { m!^[+-/*]$! } #tokens;
my #numstack = grep { $_ !~ m!^[+-/*]$! } #tokens;
for my $op (#opstack) {
splice #numstack, 0, 2, $proc{$op}->(#numstack[1,0]);
}
return $numstack[0];
}
}
say calc("123 - 10 + 4 * 10");
A more robust version would enforce an operator between every pair of numbers and have other error/sanity checking, of course.
Why not using the most amusing parts of Perl ?
This works and will return 73 if you enter the given test-case:
#!/usr/bin/env perl
use warnings;
use strict;
use feature 'say';
while (<>) { # while we get input
chomp;s/ //g;
1 while s/\d+[+\-*\/]\d+$/$&/ee;
say; # print result
}
If you want to understand how it works, just replace the no-op "1" to some STDERR output :
while (<>) {
chomp;s/ //g;
print STDERR "eval'd ($&) -> $_" while s/\d+[+\-*\/]\d+$/$&/ee;
say;
}
> ./test.pl
123 - 10 + 4 * 10
eval'd (4*10) -> 123-10+40
eval'd (10+40) -> 123-50
eval'd (123-50) -> 73
73
In a comment to my answer to your previous question, I said you could reverse the calculation by using reverse, and I see you have implemented that code.
As you have noticed, I assume, this is not true, because it would also invert the operations. I.e. 123 - 50 would become 50 - 123. I was a little careless in that comment. You can however achieve the same effect if you just restore the order of the operands in the calc() call with another use of reverse.
$main = calc(reverse($main, splice #ops, 0, 2)); # take 2 items off the list and process
That would mean that your string 123 - 10 + 4 * 10 would first become a list
10 * 4 + 10 - 123
And then it would be called
calc(4, '*', 10) # 40
calc(10, '+', 40) # 50
calc(123, '-', 50) # 73
I have this file which reads
001,Time-in,2017-06-25 08:04:42,08:00:00,
001,Time-out,2017-06-25 17:04:42,17:00:00,
001,Time-in,2017-06-25 18:04:42,18:00:00,
001,Time-out,2017-06-25 22:04:42,22:00:00,
...
where field 1 is the ID number; 2 is the action performed; 3 is the exact timestamp; and 4 is the rounded off time.
I would like to calculate the total hours per ID based on field 4. I know I can use the formula
((Out2+Out1)-(In2+In1))
or
((Out1-In1)+(Out2-In2))
to get the total hours, but I'm quite stuck as to how I should begin.
I would like to get this output:
001,13
002,12
..,..
..,..
Where field 1 is the ID and 2 will be the total hours computed.
Also, please note that the real file would be jumbled and not sorted like the example above. If any of the required entries are missing, i.e one time-out missing etc., it should just print that it skipped that particular ID.
Any thoughts regarding this would be extremely helpful.
Thanks.
$ cat tst.awk
BEGIN { FS="[-, :]" }
$3=="in" { tin[$1] += $10 }
$3=="out" { tout[$1] += $10 }
END {
for (key in tin) {
print key, tout[key] - tin[key]
}
}
$ awk -f tst.awk file
001 13
(No error handling or error recovery below.)
I'd probably write a function to return epoch time, given an ISO timestamp. Epoch time makes the arithmetic easy. But it uses the full timestamp, not your rounded values.
function epoch_time(ts) {
gsub("-", " ", ts)
gsub(":", " ", ts)
return mktime(ts)
}
Assuming we can rely on the format on the input file--a BIG assumption--you can use pretty simple code to select and process each line of the input file.
$2 == "Time-in" {
timein = epoch_time($3)
}
$2 == "Time-out" {
timeout = epoch_time($3)
# Add the result to any existing value for this id number.
# Express in hours.
output[$1] += (((timeout - timein) / 60) / 60)
}
END {
for (key in output) print key, output[key]
}
So the full code would look like this,
# timestamp.awk
#
$2 == "Time-in" {
timein = epoch_time($3)
}
$2 == "Time-out" {
timeout = epoch_time($3)
# Add the result to any existing value for this id number.
# Express in hours.
output[$1] += (((timeout - timein) / 60) / 60)
}
END {
for (key in output) print key, output[key]
}
function epoch_time(ts) {
gsub("-", " ", ts)
gsub(":", " ", ts)
return mktime(ts)
}
. . . and I'd call it like this.
$ awk -F, -f timestamp.awk datafilename
For this data, I get the output farther below.
001,Time-in,2017-06-25 08:04:42,08:00:00,
001,Time-out,2017-06-25 17:04:42,17:00:00,
001,Time-in,2017-06-25 18:04:42,18:00:00,
001,Time-out,2017-06-25 22:04:42,22:00:00,
002,Time-in,2017-06-25 09:04:42,08:00:00,
002,Time-out,2017-06-25 17:04:42,17:00:00,
002,Time-in,2017-06-25 19:04:42,18:00:00,
002,Time-out,2017-06-25 22:04:42,22:00:00,
$ awk -F, -f timestamp.awk datafilename
002 11
001 13
I want to create a function in Lilypond that accepts one note as input and returns the note with some markup applied. Specifically, I want to simplify something like the following:
\relative c' { d^\markup{\hspace #2 \smaller +1}-\bendAfter #+1 }
to something along the lines of
\relative c' { \bend{d} }
Currently I have the following snippet:
mF = \markup{\hspace #2 \smaller +1}
bF = \bendAfter #+1
bendF = #(define-music-function (parser location note) (ly:music?)
#{ $note^\mF-\bF #}
)
\relative c' { d^\mF-\bF }
\relative c' { \bendF{d} }
\version "2.16.2"
It seems that the data type ly:music? is not the right one, or it is impossible to append the markup directly, and I end up with not very descriptive interpreter errors.
What is the best way to achieve this effect?
This may be not the solution you are looking for, but you might be able to solve your problem by using an event function with no arguments instead of a music function (thus working around the ly:music? problem). Try:
\version "2.17.95"
mF = \markup{\hspace #2 \smaller +1}
bF = \bendAfter #+1
bendF = #(define-event-function
(parser location )
( )
#{
^\mF-\bF
#}
)
\relative c' { d^\mF-\bF }
\relative c' { d\bendF }