I have a two requirements:
I must concatenate some fields from a file in a Cobol program. The way i must concatenate is based on one of the aforementioned field. The concatenated fields must be outputted in a new file.
I must then sort this new file with a sort utility invoked by JCL.
The Issue
I need to sort same file for 2 conditions. I have tried with ifthen outrec build. How can I sort it in one pass?
Here is a source-code example :
ID DIVISION.
PROGRAM-ID. FOO.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
Select Infil assign to inp001.
Select Outfil assign to out001.
DATA DIVISION.
FILE SECTION.
FD Infil.
01 Main.
03 A.
05 ws-Pc. Pic x(1).
05 filler Pic x(5).
03 B. Pic x(4).
03 C. Pic x(4).
03 D. Pic 9(13)V99.
03 E. Pic x(13).
FD Outfil.
01 Temp Pic x(42).
WORKING-STORAGE SECTION.
01 file-flag Pic x(01).
88 file-end value 'Y'.
88 not-file-end value 'N'.
PROCEDURE DIVISION.
Open input Infil
Open output Outfil
read Infil
at end
set file-end to true
not at end
set not-file-end to true
end-read
Perform until file-end
If ws-Pc = 3
String A B C Delimited by size
into Temp
End-String
Else
String A B C E Delimited by size
into Temp
End-String
End-if
Write Temp
read Infil
at end
Set file-end to true
end-read
end-Perform.
end program foo.
Here is the logic I need for the sort utility :
If ws-Pc=3
Sort(fieldA,fieldB)
Else
Sort(fieldA,fieldB,fieldE)
End-if.
I can propose you three variations :
If you are sure that your last 13 characters are the same (spaces for instance) in the case without a field E (ws-pc equal to three) you can just have this sysin:
SORT FIELDS=(1,6,CH,A,7,4,CH,A),EQUALS
Indeed, thanks to the equals all your inputs will keep their relative order once sorted. For the case ws-pc=3 it will be sorted according to field A and B. Field E plays no importance because it is the same for all.
If you are not sure that the last 13 characters are the same you can do it yourself:
INREC IFTHEN=(WHEN=(1,1,CH,EQ,C'3'),BUILD=(1,14,13X))
SORT FIELDS=(1,6,CH,A,7,4,CH,A),EQUALS
This will force your last characters to be spaces.
If you don't want to use the "EQUALS" you can create your own ordering by appending a line number in the field E when it is unused. You then have to remove it.
INREC IFTHEN=(WHEN=(1,1,CH,EQ,C'3'),BUILD=(1,14,SEQNUM,13,ZD))
SORT FIELDS=(1,6,CH,A,7,4,CH,A)
OUTREC IFTHEN=(WHEN=(1,1,CH,EQ,C'3'),BUILD=(1,14,13X))
This error occurs on line 3 of my code and I don't know why.
I'm trying to create multiple variables with x..q, but it doesn't work.
for i=1,3 do
for q=1,3 do
x..q=i+1
print(x..q)
end
end
The output should be:
2
2
2
3
3
3
4
4
4
But instead it returns the error in the title.
If you want to create multiple global variables, use code like this:
for i=1,3 do
for q=1,3 do
_G["x"..q]=i+1
print(_G["x"..q])
end
end
This code will create globals x1, x2, and x3.
But I think you'd be better off using a table:
x={}
for i=1,3 do
for q=1,3 do
x[q]=i+1
print(x[q])
end
end
I believe you are using the operator .. unintentionally.
When accessing a value of a table, the syntax is x.q. Programming in Lua: 2.5 – Tables
To represent records, you use the field name as an index. Lua supports this representation by providing a.name as syntactic sugar for a["name"]. So, we could write the last lines of the previous example in a cleanlier manner as
a.x = 10 -- same as a["x"] = 10
print(a.x) -- same as print(a["x"])
print(a.y) -- same as print(a["y"])
When concatenating a string the syntax is x .. q.
Programming in Lua: 3.4 – Concatenation
Lua denotes the string concatenation operator by ".." (two dots). If any of its operands is a number, Lua converts that number to a string.
print("Hello " .. "World") --> Hello World
print(0 .. 1) --> 01
Reading this page on TLDP: http://www.tldp.org/LDP/abs/html/mathc.html
I've found the following command:
bash$ echo "16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D68736142snlbxq" | dc
Bash
And I was just wondering: someone knows what type of hash is that and how I can convert a simple text to generate that kind of hash?
thanks
Relatively good tutorial is here. Using it, you'll get the next decomposition:
16i - the input will be hexadecimal (like in bc - ibase=16)
[q] - the [..] mean string. So this store a string q to the top of stack. Usually the [....] is a series of commands stored for later execution (like a macro), in this case the command q - quit.
the s - take the top of stack and store it to register identified by the next letter, so the [q]sa together in this case mean: store the the string q into register a
same with the next, store the string ln0=aln100%Pln100/snlbx into register b
the next A0D68736142sn, store the A0D68736142 into register n. In this case not a string, but because we have input hexaadecimal, this is an hexadecimal number
The above is an like a preparation phase, translated into common programming language:
$a = "q";
$b = "ln0=aln100%Pln100/snlbx";
$n = 0xA0D68736142";
The stack is now empty (everything is stored in registres).
The next is the final calculation:
the l mean take the the the value from the followed register, and put it to the top of stack so the lb mean: take the value of register b.
the x mean: execute it as an series of commands - in this case read it as eval "$b";
the last q mean quit
now need decompose the ln0=aln100%Pln100/snlbx (content of register b - what is eval-ing.)
ln - as above, take the value from the register n in our case: the hexa-number
next is a tricky part: 0=a, take the top of stack, and if it is zero execute the string (macro) stored in the registry "a" (in our case this is a "q" - quit), e.g. like:
if( $n == 0 ) eval "a"; #a contains "q" = quit
if the $n isn't zero, take the content of regsiter n again (ln) (put to the top of stack)
put the number 100 (it is hexa) to to top of stack
% modulo the two numbers from the top of the stack (so: $n % 0x100) and put it to the top of the stack
print the top of stack as an ascii string ( chr($stack) )
ln take again the number $n (again, it comes to the top of stack)
put 100 to the stack
/ divide the to numbers in the stack (result comes into the top)
sn store the stack into the $n (replaces the original number)
lbx - as above - eval the register b
So, in short:
from the number 0xA0D68736142 stored in $n,
modulo it by 0x100 get the last two digits, convert it to ascii and print it,
divide it by 0x100 (removes last two digits) - and store it to $n
repeat until nothing remained (zero)
For the 0xA0D68736142 you will get (use man ascii)
42 - B
61 - a
73 - s
68 - h
0D - \r
A (as 0A) - \n
Creating such hexsting from normal ascii string with perl
perl -E '$s=reverse("Bash\r\n");$s =~ s/(.)/sprintf("%02x",ord($1))/seg;say uc $s'
prints
0A0D68736142
or
perl -E '$s=reverse("Stackoverflow rocks\n");$s =~ s/(.)/sprintf("%02x",ord($1))/seg;say uc $s'
0A736B636F7220776F6C667265766F6B63617453
and
echo "16i[q]sa[ln0=aln100%Pln100/snlbx]sb0A736B636F7220776F6C667265766F6B63617453snlbxq" | dc
prints:
Stackoverflow rocks
Ps: with dc is one strange thing - it is much-much easier to read and understand a "program" as creating one. :)
I'm trying to read in a file consisting of lines of text of the following sort of form...
first value 1352.2 second value 12 third value 32323
first value 1233.2 second value 22 third value 23333
first value 1233.1 second value 21 third value 64344
so I'm looking for a function analagous to fscanf or sscanf to munch each line up in one go. Is there such a function or must I pick apart each line by hand (there are several different kinds of lines).
There's no equivalent of sscanf. I would just pick the lines apart by hand using Mid(). It's fairly easy.
Mid(string, start, length) will return a substring, starting at character start, and length characters long.
start is 1-based - the first character in the string is number 1.
Think carefully about the start and length. What will the file look like if it contains a really large number? Probably the number will extend further to the left (if the numbers are right-aligned in the file, which is common in my experience - your mileage may vary).
Use Val to convert the substrings to numbers
Val always uses dot as decimal separator - is that what you need?
Personally I would avoid Input #. Input # is intended for reading files written from VB6 using Write #. If you try to read an arbitrary file format with Input #, you might encounter odd edge cases.
While MarkJ has given you the VB6 way of doing things, you may want to check out FWIW:
http://www.freevbcode.com/ShowCode.asp?ID=3806
"C String Functions SScanf and StrTok Implemented in VB"
It implements a function ScanString() that's supposed to be an emulation of sscanf().
Given a file like that, you can use whatever method you like to read the file line by line, then use the Trim and Split functions to create a string array of space-delimited strings for each line. Then parse the numbers from the resulting array by keeping those elements that return True from the IsNumeric function:
Put this in the immediate window to see how this would work:
s = Split(Trim("first value 1352.2 second value 12 third value 32323"))
For x = LBound(s) To UBound(s): _
? "'", x, s(x), IsNumeric(s(x)): _
Next x
When you press enter after Next x, you'll see this, where every number is followed by a "True":
' 0 first False
' 1 value False
' 2 1352.2 True
' 3 False
' 4 False
' 5 False
' 6 False
' 7 False
' 8 second False
' 9 value False
' 10 False
' 11 False
' 12 False
' 13 False
' 14 12 True
' 15 False
' 16 False
' 17 False
' 18 False
' 19 False
' 20 third False
' 21 value False
' 22 False
' 23 False
' 24 False
' 25 32323 True
Note: I put the leading double quote on each print line so that the syntax highlighting wouldn't mess with the output.
The Input statement should be sufficient for most cases (maybe with some logic to detect the type of line and call the relevant input statement).
There is a fairly comprehensive examination of different file IO commands in VB6 with some nice examples of reading a 'COBOL-style' fixed with file over here.
If you are dealing with an odd or inconsistent format that Input can't deal with, as you say it is possible to pick apart by hand. This might be the best option as you mention there are different formats.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
Introduction
A valid Sudoku grid is filled with numbers 1 to 9, with no number occurring more than once in each sub-block of 9, row or column. Read this article for further details if you're unfamiliar with this popular puzzle.
Challenge
The challenge is to write the shortest program that validates a Sudoku grid that might not be full.
Input will be a string of 9 lines of 9 characters each, representing the grid. An empty cell will be represented by a .. Your output should be Valid if the grid is valid, otherwise output Invalid.
Example
Input
123...789
...456...
456...123
789...456
...123...
564...897
...231...
897...564
...564...
Output
Valid
Input
123456789
987654321
123456789
123456789
987654321
123456789
123456789
987654321
123456789
Output
Invalid
Code Golf Rules
Please post your shortest code in any language that solves this problem. Input and output may be handled via stdin and stdout or by other files of your choice.
Winner will be the shortest solution (by byte count) in a language with an implementation existing prior to the posting of this question. So while you are free to use a language you've just made up in order to submit a 0-byte solution, it won't count, and you'll probably get downvotes.
Golfscript: 56
n%{zip''+9/.{'.'-..&=}%$0=\}:|2*{3/}%|;**"InvV"3/="alid"
C: 165 162 161 160 159
int v[1566],x,y=9,c,b;main(){while(y--)for(x=9;x--+1;)if((c
=getchar()*27)>1242)b|=v[x+c]++|v[y+9+c]++|v[x-x%3+y/3+18+c]
++;puts(b?"Invalid":"Valid");return 0;}
The two newlines are not needed. One char saved by josefx :-) ...
Haskell: 207 230 218 195 172
import List
t=take 3
h=[t,t.drop 3,drop 6]
v[]="V"
v _="Inv"
f s=v[1|v<-[s,transpose s,[g=<<f s|f<-h,g<-h]],g<-map(filter(/='.'))v,g/=nub g]++"alid\n"
main=interact$f.lines
Perl: 168 128
$_=join'',<>;#a=/.../g;print+(/(\d)([^\n]{0,8}|(.{10})*.{9})\1/s
+map"#a[$_,$_+3,$_+6]"=~/(\d).*\1/,0..2,9..11,18..20)?Inv:V,alid
The first regex checks for duplicates that are in the same row and column; the second regex handles duplicates in the "same box".
Further improvement is possible by replacing the \n in the first regex with a literal newline (1 char), or with >= Perl 5.12, replacing [^\n] with \N (3 char)
Earlier, 168 char solution:
Input is from stdin, output is to stderr because it makes things so easy. Linebreaks are optional and not counted.
$_=join'',<>;$m=alid.$/;$n=Inv.$m;/(\d)(\N{0,8}|(.{10})*.{9})\1/s&&
die$n;#a=/.../g;for$i(0,8,17){for$j($i..$i+2){
$_=$a[$j].$a[$j+3].$a[$j+6];/(\d).*\1/&&die$n}}die"V$m"
Python: 230 221 200 185
First the readable version at len=199:
import sys
r=range(9)
g=[raw_input()for _ in r]
s=[[]for _ in r*3]
for i in r:
for j in r:
n=g[i][j]
for x in i,9+j,18+i/3*3+j/3:
<T>if n in s[x]:sys.exit('Invalid')
<T>if n>'.':s[x]+=n
print'Valid'
Since SO doesn't display tab characters, I've used <T> to represent a single tab character.
PS. the same approach minEvilized down to 185 chars:
r=range(9)
g=[raw_input()for _ in r]
s=['']*27
for i in r:
for j in r:
for x in i,9+j,18+i/3*3+j/3:n=g[i][j];s[x]+=n[:n>'.']
print['V','Inv'][any(len(e)>len(set(e))for e in s)]+'alid'
Perl, 153 char
#B contains the 81 elements of the board.
&E tests whether a subset of #B contains any duplicate digits
main loop validates each column, "block", and row of the puzzle
sub E{$V+="#B[#_]"=~/(\d).*\1/}
#B=map/\S/g,<>;
for$d(#b=0..80){
E grep$d==$_%9,#b;
E grep$d==int(($_%9)/3)+3*int$_/27,#b;
E$d*9..$d*9+8}
print$V?Inv:V,alid,$/
Python: 159 158
v=[0]*244
for y in range(9):
for x,c in enumerate(raw_input()):
if c>".":
<T>for k in x,y+9,x-x%3+y//3+18:v[k*9+int(c)]+=1
print["Inv","V"][max(v)<2]+"alid"
<T> is a single tab character
Common Lisp: 266 252
(princ(let((v(make-hash-table))(r "Valid"))(dotimes(y 9)(dotimes(x
10)(let((c(read-char)))(when(>(char-code c)46)(dolist(k(list x(+ 9
y)(+ 18(floor(/ y 3))(- x(mod x 3)))))(when(>(incf(gethash(+(* k
9)(char-code c)-49)v 0))1)(setf r "Invalid")))))))r))
Perl: 186
Input is from stdin, output to stdout, linebreaks in input optional.
#y=map/\S/g,<>;
sub c{(join'',map$y[$_],#$h)=~/(\d).*\1/|c(#_)if$h=pop}
print(('V','Inv')[c map{$x=$_;[$_*9..$_*9+8],[grep$_%9==$x,0..80],[map$_+3*$b[$x],#b=grep$_%9<3,0..20]}0..8],'alid')
(Linebreaks added for "clarity".)
c() is a function that checks the input in #y against a list of lists of position numbers passed as an argument. It returns 0 if all position lists are valid (contain no number more than once) and 1 otherwise, using recursion to check each list. The bottom line builds this list of lists, passes it to c() and uses the result to select the right prefix to output.
One thing that I quite like is that this solution takes advantage of "self-similarity" in the "block" position list in #b (which is redundantly rebuilt many times to avoid having #b=... in a separate statement): the top-left position of the ith block within the entire puzzle can be found by multiplying the ith element in #b by 3.
More spread out:
# Grab input into an array of individual characters, discarding whitespace
#y = map /\S/g, <>;
# Takes a list of position lists.
# Returns 0 if all position lists are valid, 1 otherwise.
sub c {
# Pop the last list into $h, extract the characters at these positions with
# map, and check the result for multiple occurences of
# any digit using a regex. Note | behaves like || here but is shorter ;)
# If the match fails, try again with the remaining list of position lists.
# Because Perl returns the last expression evaluated, if we are at the
# end of the list, the pop will return undef, and this will be passed back
# which is what we want as it evaluates to false.
(join '', map $y[$_], #$h) =~ /(\d).*\1/ | c(#_) if $h = pop
}
# Make a list of position lists with map and pass it to c().
print(('V','Inv')[c map {
$x=$_; # Save the outer "loop" variable
[$_*9..$_*9+8], # Columns
[grep$_%9==$x,0..80], # Rows
[map$_+3*$b[$x],#b=grep$_%9<3,0..20] # Blocks
} 0..8], # Generates 1 column, row and block each time
'alid')
Perl: 202
I'm reading Modern Perl and felt like coding something... (quite a cool book by the way:)
while(<>){$i++;$j=0;for$s(split//){$j++;$l{$i}{$s}++;$c{$j}{$s}++;
$q{(int(($i+2)/3)-1)*3+int(($j+2)/3)}{$s}++}}
$e=V;for$i(1..9){for(1..9){$e=Inv if$l{$i}{$_}>1or$c{$i}{$_}>1or$q{$i}{$_}>1}}
print $e.alid
Count is excluding unnecessary newlines.
This may require Perl 5.12.2.
A bit more readable:
#use feature qw(say);
#use JSON;
#$json = JSON->new->allow_nonref;
while(<>)
{
$i++;
$j=0;
for $s (split //)
{
$j++;
$l{$i}{$s}++;
$c{$j}{$s}++;
$q{(int(($i+2)/3)-1)*3+int(($j+2)/3)}{$s}++;
}
}
#say "lines: ", $json->pretty->encode( \%l );
#say "columns: ", $json->pretty->encode( \%c );
#say "squares: ", $json->pretty->encode( \%q );
$e = V;
for $i (1..9)
{
for (1..9)
{
#say "checking {$i}{$_}: " . $l{$i}{$_} . " / " . $c{$i}{$_} . " / " . $q{$i}{$_};
$e = Inv if $l{$i}{$_} > 1 or $c{$i}{$_} > 1 or $q{$i}{$_} > 1;
}
}
print $e.alid;
Ruby — 176
f=->x{x.any?{|i|(i-[?.]).uniq!}}
a=[*$<].map{|i|i.scan /./}
puts f[a]||f[a.transpose]||f[a.each_slice(3).flat_map{|b|b.transpose.each_slice(3).map &:flatten}]?'Invalid':'Valid'
Lua, 341 bytes
Although I know that Lua isn't the best golfing language, however, considering it's size, I think it's worth posting it ;).
Non-golfed, commented and error-printing version, for extra fun :)
i=io.read("*a"):gsub("\n","") -- Get input, and strip newlines
a={{},{},{}} -- checking array, 1=row, 2=columns, 3=squares
for k=1,3 do for l=1,9 do a[k][l]={0,0,0,0,0,0,0,0,0}end end -- fillup array with 0's (just to have non-nils)
for k=1,81 do -- loop over all numbers
n=tonumber(i:sub(k,k):match'%d') -- get current character, check if it's a digit, and convert to a number
if n then
r={math.floor((k-1)/9)+1,(k-1)%9+1} -- Get row and column number
r[3]=math.floor((r[1]-1)/3)+3*math.floor((r[2]-1)/3)+1 -- Get square number
for l=1,3 do v=a[l][r[l]] -- 1 = row, 2 = column, 3 = square
if v[n] then -- not yet eliminated in this row/column/square
v[n]=nil
else
print("Double "..n.." in "..({"row","column","square"}) [l].." "..r[l]) --error reporting, just for the extra credit :)
q=1 -- Flag indicating invalidity
end
end
end
end
io.write(q and"In"or"","Valid\n")
Golfed version, 341 bytes
f=math.floor p=io.write i=io.read("*a"):gsub("\n","")a={{},{},{}}for k=1,3 do for l=1,9 do a[k][l]={0,0,0,0,0,0,0,0,0}end end for k=1,81 do n=tonumber(i:sub(k,k):match'%d')if n then r={f((k-1)/9)+1,(k-1)%9+1}r[3]=f((r[1]-1)/3)+1+3*f((r[2]-1)/3)for l=1,3 do v=a[l][r[l]]if v[n]then v[n]=nil else q=1 end end end end p(q and"In"or"","Valid\n")
Python: 140
v=[(k,c) for y in range(9) for x,c in enumerate(raw_input()) for k in x,y+9,(x/3,y/3) if c>'.']
print["V","Inv"][len(v)>len(set(v))]+"alid"
ASL: 108
args1["\n"x2I3*x;{;{:=T(T'{:i~{^0}?})}}
{;{;{{,0:e}:;{0:^},u eq}}/`/=}:-C
dc C#;{:|}C&{"Valid"}{"Invalid"}?P
ASL is a Golfscript inspired scripting language I made.