What is a flip-flop operator?
The flip-flop operator in Perl evaluates to true when the left operand is true, and keeps evaluating to true until the right operand is true. The left and right operand could be any kind of expression, but most often it is used with regexes.
With regexes, it is useful for finding all the lines between two markers. Here is a simple example that shows how it works:
use Modern::Perl;
while (<DATA>)
{
if (/start/ .. /end/)
{
say "flip flop true: $_";
}
else
{
say "flip flop false: $_";
}
}
__DATA__
foo
bar
start
inside
blah
this is the end
baz
The flip flop operator will be true for all lines from start
until this is the end
.
The two dot version of the operator allows first and second regex to both match on the same line. So, if your data looked like this, the above program would only be true for the line start blah end
:
foo
bar
start blah end
inside
blah
this is the end
baz
If you don't want the first and second regexes to match the same line, you can use the three dot version: if (/start/ ... /end/)
.
Note that care should be taken not to confuse the flip-flop operator with the range operator. In list context, ..
has an entirely different function: it returns a list of sequential values. e.g.
my @integers = 1 .. 1000; #makes an array of integers from 1 to 1000.
I'm not familiar with Ruby, but Lee Jarvis's link suggests that it works similarly.
Is there a functional programming concept equivalent to the flip-flop operator in Perl or Ruby?
In a functional language such as haskell, you would pass in the flip and flop conditions as predicates, and filter an input list based on it. For example, the following is a definition of flipflop
in haskell (don't worry about the implementation if you don't know haskell - the key part is how it is used):
flipflop flip flop =
uncurry (++) . second (take 1) . break flop . dropWhile (not . flip)
This is how it can be used:
> flipflop (== 3) (== 5) [1..10]
[3,4,5]
It is an example of making an effectively new language construct just by using higher ordered function.
I don't know if there is a special name for that construct in functional languages.
DRY up flip-flop operator
I would starts with something like this:
LOGLEVELS = ['debug', 'info', 'warn', 'error', 'fatal']
def loglevel?(level, line)
level = level.upcase
(line =~ /<#{level}>/ .. line =~ /<(?!#{level}).+>/) && line !~ /<(?!#{level}).+>/
end
def error_sort
File.readlines(@log_file).each do |line|
LOGLEVES.each do |level|
File.open("#{level}.txt", "a") << line if loglevel?(level, line)
end
end
end
flip-flop, latch basic concept
The utility of flip flop is to store state and make it stable.
For your statement about making "input = output", you have to understand that every change in the input line is not necessarily the input for the flip flop. And another thing is that output can be some operation of previous output and present input then you need previous output which you should store in somewhere, for which flip flop is used (and register is a group of flip flops).
In flip flop, we use clock to synchronize the operation. Depending upon the types of flip flop i.e. edge-trigger or level-trigger, the input in the flip flop affects its output. For example: for level-trigger flip flop, the input in the flip flop affects its output only when the clock is high.
So, for your question that "inputs can be put to zeros to maintain the outputs", you are right that it helps to maintain the outputs but that is not only the case to maintain the outputs. When the clock is low, change in inputs does not affect the output.
Counting changes in an array
Below one is solution I believe. Sure there is more room to refactor it, you can start from here.
a = ["red", "orange", "green", "red", "yellow", "blue", "green"]
a.reject {|e| !['red', 'green'].include? e }
.each_cons(2)
.select{|e| e == ['red', 'green']}
.size
A more artistic version.
def neither_red_nor_green e
!['red', 'green'].include? e
end
def red_followed_by_green ary
ary == ['red', 'green']
end
a.reject(&method(:neither_red_nor_green))
.each_cons(2)
.select(&method(:red_followed_by_green))
.size
UPDATE
Thanks to @Stefan for below suggestions.
def either_red_or_green e
['red', 'green'].include? e
end
def red_followed_by_green ary
ary == ['red', 'green']
end
a.select(&method(:either_red_or_green))
.each_cons(2)
.count(&method(:red_followed_by_green))
UPDATE
As Stefan Pochmann proposed,
a.select(&method(:either_red_or_green))
.each_cons(2)
.count(['red', 'green'])
will do the same work, without needing another method call.
Related Topics
Ruby Read CSV File as Utf-8 And/Or Convert Ascii-8Bit Encoding to Utf-8
Differencebetween Using .Exists, and .Present? in Ruby
How to Use Hash Keys as Methods on a Class
Ruby 1.9 Hash with a Dash in a Key
Is There a Built-In Binary-Search in Ruby
Missing Symbol When Installing Ruby-2.3.0 on Os X 10.11.6 by Rvm
Docker for MAC - Mkmf.Rb Can't Find Header Files for Ruby
Devise Logged in Root Route Rails 3
How to Pass Multiple Arguments to a Ruby Method as an Array
Set Attribute Dynamically of Ruby Object
Ruby 'Encode': "\Xc3" from Ascii-8Bit to Utf-8 (Encoding::Undefinedconversionerror)
Rails Gem Rails3-Jquery-Autocomplete How to Scope by User