Remove nTh record from array using loop [closed] - ruby
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm writing a program that reads a .csv file, and then loops through it removing every 10th record it encounters before outputting it.
I've been stuck on what I believe is a syntax issue for a while now and just can't seem to nail it. Anyone mind having a look?
lines = []
i = 0
elements = []
element2 = []
output = []
file = File.open("./properties.csv", "r")
while (line = file.gets)
i += 1
# use split to break array up using commas
arr = line.split(',')
elements.push({ id: arr[0], streetAddress: arr[1], town: arr[2], valuationDate: arr[3], value: arr[4] })
end
file.close
# filter out blanks and nill rows
x = elements.select { |elements| elements[:id].to_i >= 0.1}
# Loop to remove every 10th record
e = 0
d = 1
loop do x.length
if e == (10 * d)
d ++
e ++
else
x = elements.select[e]
e ++
end
puts x
puts "#{x.length} house in list, #{d} records skipped."
CSV FILE
ID,Street address,Town,Valuation date,Value
1,1 Northburn RD,WANAKA,1/1/2015,280000
2,1 Mount Ida PL,WANAKA,1/1/2015,280000
3,1 Mount Linton AVE,WANAKA,1/1/2015,780000
4,1 Kamahi ST,WANAKA,1/1/2015,155000
5,1 Kapuka LANE,WANAKA,1/1/2015,149000
6,1 Mohua MEWS,WANAKA,1/1/2015,560000
7,1 Kakapo CT,WANAKA,1/1/2015,430000
8,1 Mt Gold PL,WANAKA,1/1/2015,1260000
9,1 Penrith Park DR,WANAKA,1/1/2015,1250000
10,1 ATHERTON PL,WANAKA,1/1/2015,650000
11,1 WAIMANA PL,WANAKA,1/1/2015,780000
12,1 ROTO PL,WANAKA,1/1/2015,1470000
13,1 Toms WAY,WANAKA,1/1/2015,2230000
14,1 MULBERRY LANE,WANAKA,1/1/2015,415000
15,1 Range View PL,WANAKA,1/1/2015,300000
16,1 Clearview ST,WANAKA,1/1/2015,1230000
17,1 Clutha PL,WANAKA,1/1/2015,700000
18,1 Centre CRES,WANAKA,1/1/2015,295000
19,1 Valley CRES,WANAKA,1/1/2015,790000
20,1 Edgewood PL,WANAKA,1/1/2015,365000
21,1 HUNTER CRES,WANAKA,1/1/2015,335000
22,1 KOWHAI DR,WANAKA,1/1/2015,480000
23,1 RIMU LANE,WANAKA,1/1/2015,465000
24,1 CHERRY CT,WANAKA,1/1/2015,495000
25,1 COLLINS ST,WANAKA,1/1/2015,520000
26,1 AUBREY RD,WANAKA,1/1/2015,985000
27,1 EELY POINT RD,WANAKA,1/1/2015,560000
28,1 LINDSAY PL,WANAKA,1/1/2015,385000
29,1 WINDERS ST,WANAKA,1/1/2015,760000
30,1 Manuka CRES,WANAKA,1/1/2015,510000
31,1 WILEY RD,WANAKA,1/1/2015,420000
32,1 Baker GR,WANAKA,1/1/2015,820000
33,1 Briar Bank DR,WANAKA,1/1/2015,1260000
34,1 LAKESIDE RD,WANAKA,1/1/2015,440000
35,1 PLANTATION RD,WANAKA,1/1/2015,345000
36,1 Allenby PL,WANAKA,1/1/2015,640000
37,1 ROB ROY LANE,WANAKA,1/1/2015,380000
38,1 Ansted PL,WANAKA,1/1/2015,590000
39,1 Fastness CRES,WANAKA,1/1/2015,640000
40,1 APOLLO PL,WANAKA,1/1/2015,385000
41,1 AEOLUS PL,WANAKA,1/1/2015,370000
42,1 Peak View RDGE,WANAKA,1/1/2015,1750000
43,1 Moncrieff PL,WANAKA,1/1/2015,530000
44,1 Islington PL,WANAKA,1/1/2015,190000
45,1 Hidden Hills DR,WANAKA,1/1/2015,1280000
46,1 Weatherall CL,WANAKA,1/1/2015,425000
47,1 Terranova PL,WANAKA,1/1/2015,900000
48,1 Cliff Wilson ST,WANAKA,1/1/2015,1200000
49,1 TOTARA TCE,WANAKA,1/1/2015,460000
50,1 Koru WAY,WANAKA,1/1/2015,570000
51,1 Bovett PL,Wanaka,1/1/2015,495000
52,1 Pearce PL,Wanaka,1/1/2015,675000
53,1 Ironside DR,WANAKA,1/1/2015,570000
54,1 Bob Lee PL,WANAKA,1/1/2015,610000
55,1 Hogan LANE,WANAKA,1/1/2015,395000
56,1 ARDMORE ST,WANAKA,1/1/2015,1190000
57,1 Bullock Creek LANE,WANAKA,1/1/2015,11125000
58,1 DUNMORE ST,WANAKA,1/1/2015,1300000
59,1 Primary LANE,WANAKA,1/1/2015,430000
60,1 SYCAMORE PL,WANAKA,1/1/2015,720000
61,1 FAULKS TCE,WANAKA,1/1/2015,780000
62,1 Alpha CL,WANAKA,1/1/2015,500000
63,1 Coromandel ST,WANAKA,1/1/2015,530000
64,1 Niger ST,WANAKA,1/1/2015,475000
65,1 Maggies Way,WANAKA,1/1/2015,375000
66,1 Hollyhock LANE,QUEENSTOWN,1/1/2015,1080000
67,1 ELDERBERRY CRES,WANAKA,1/1/2015,1340000
68,1 Foxglove HTS,WANAKA,1/1/2015,2520000
69,1 MEADOWSTONE DR,WANAKA,1/1/2015,650000
70,1 OAKWOOD PL,WANAKA,1/1/2015,580000
71,1 MEADOWBROOK PL,WANAKA,1/1/2015,645000
72,1 Jessies CRES,WANAKA,1/1/2015,320000
73,1 Lansdown ST,WANAKA,1/1/2015,700000
74,1 Stonebrook DR,WANAKA,1/1/2015,640000
75,1 Hyland ST,WANAKA,1/1/2015,500000
76,1 TAPLEY PADDOCK,WANAKA,1/1/2015,720000
77,1 Homestead CL,WANAKA,1/1/2015,1750000
78,1 NORMAN TCE,WANAKA,1/1/2015,620000
79,1 Sunrise Bay DR,WANAKA,1/1/2015,3000000
80,1 LARCH PL,WANAKA,1/1/2015,570000
81,1 MILL END,WANAKA,1/1/2015,600000
82,1 Bills WAY,WANAKA,1/1/2015,750000
83,1 Heuchan LANE,WANAKA,1/1/2015,610000
84,1 SARGOOD DR,WANAKA,1/1/2015,455000
85,1 Frederick ST,WANAKA,1/1/2015,455000
86,1 Connell TCE,WANAKA,1/1/2015,600000
87,1 Soho ST,QUEENSTOWN,1/1/2015,320000
88,1 Hikuwai DR,ALBERT TOWN,1/1/2015,280000
89,1 Harrier LANE,WANAKA,1/1/2015,1000000
90,1 Ewing PL,WANAKA,1/1/2015,780000
91,1 Sherwin AVE,ALBERT TOWN,1/1/2015,440000
92,1 Hardie PL,WANAKA,1/1/2015,830000
93,1 Finch ST,ALBERT TOWN,1/1/2015,540000
94,1 Poppy LANE,ALBERT TOWN,1/1/2015,395000
95,1 Warbler LANE,ALBERT TOWN,1/1/2015,410000
96,1 Balneaves LANE,WANAKA,1/1/2015,250000
97,1 Mill Green,Arrowtown,1/1/2015,800000
require 'csv'
elements = {}
CSV.foreach("properties.csv", :headers => true, :header_converters => :symbol) do |row|
elements[row.fields[0]] = Hash[row.headers[1..-1].zip(row.fields[1..-1])]
end
d = 0
e = 0
elements.delete_if do |key, value|
e += 1
if e == 10
e = 0
d += 1
end
e == 0
end
puts "#{elements.length} house in list, #{d} records skipped."
At the end of this, elements will have every 10th row removed, and d contains the number of rows removed.
Related
Fixing my basic Lua battle system [closed]
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 6 years ago. Improve this question This is a problem that I cannot seem to fix. I am a very new programmer and I love to code, however, I need help with this extremely basic battle system that I'm sure all you won't mind giving me. It isn't good looking or clean, so any tips on how I could shorten my code will also be greatly appreciated. local function battle() -- All of this is 100% unfinished, by the way n = math.random(10) + 1 -- Everybody's HP, enemy HP randomly generated number from 10 to 100 enemyhp = 10*n herohp = 100 io.write("Your HP: ") io.write(herohp) io.write(" ") io.flush() io.write("Enemy HP: ") io.write(enemyhp) io.write(" ") io.flush() if enemyhp <= 0 then print("You won!") end local function attack() -- Attacking the enemy or running away print("|Attack|Flee|") input = io.read() if input = "attack" then -- This is where my error is attackdamage = math.random(51) if attackdamage = 51 then print("Critical Hit!") enemyhp - 100 else enemyhp - attackdamage print("Enemy took ") io.write(attackdamage) io.write(" damage!") elseif input = "flee" then print("You ran away!") end end end Thank you.
You are missing the end of your if block. It should be if enemyhp <= 0 then print("You won!") end Second problem is the line you point to: You need to compare using two equal signs (==) instead of one: if input == "attack" then Then when you assign value to some variable, you need to use one equal sign. Otherwise it is just expression with no meaning. enemyhp = enemyhp - 100 and then the same errors repeat (you have one additional end in the end too). Full code, you can compile/run: http://ideone.com/dgPoZo local function battle() -- All of this is 100% unfinished, by the way n = math.random(10) + 1 -- Everybody's HP, enemy HP randomly generated number from 10 to 100 enemyhp = 10*n herohp = 100 io.write("Your HP: ") io.write(herohp) io.write(" ") io.flush() io.write("Enemy HP: ") io.write(enemyhp) io.write(" ") io.flush() if enemyhp <= 0 then print("You won!") end end local function attack() -- Attacking the enemy or running away print("|Attack|Flee|") input = io.read() if input == "attack" then -- This is where my error is attackdamage = math.random(51) if attackdamage == 51 then print("Critical Hit!") enemyhp = enemyhp - 100 else enemyhp = enemyhp - attackdamage print("Enemy took ") io.write(attackdamage) io.write(" damage!") end elseif input == "flee" then print("You ran away!") end end
Reading a line from a text file, splitting the string version of that line into two parts
Newbie learning Ruby. I am trying to take a txt file and on each line take the first 3 characters and assign them as a key, and the rest of the string as that's keys value. f = File.open("textfile.txt", "r") finalHash = {"Key" => "Data"} lineString = "" while f.gets != nil do lineString = f.gets part1 = lineString.slice(0, 2) part2 = lineString.slice(3, lineString.length) finalHash[:part1] = part2 end puts finalHash Any advice is appreciated!
the 2nd parameter of slice is the length, not the end-index, so change: part1 = lineString.slice(0, 2) to: part1 = lineString.slice(0, 3) If passed a start index and a length, returns a substring containing length characters starting at the index Also you don't need the second parameter here (this is not a bug though): part2 = lineString.slice(3, lineString.length) This is enough: part2 = lineString.slice(3)
Let's first create a file: text = <<_ Now is the time for all good Rubiests to come to the aid of their bowling team. _ FName = 'temp' File.write(FName, text) #=> 80 Now read the file a line at a time and construct the desired hash: File.foreach(FName).with_object({}) do |line, h| h[line.slice!(0,3)] = line.chomp end #=> {"Now"=>" is the", "tim"=>"e for all", "goo"=>"d Rubiests", # "to "=>"come to the", "aid"=>" of their", "bow"=>"ling team."} After reading the first line, h = { "Now"=>" is the" } line = "time for all\n" a = line.chomp #=> "time for all" b = a.slice!(0,3) #=> "tim" a #=> "e for all" h[b] = a #=> "e for all" h #=> {"Now"=>" is the", "tim"=>"e for all"} No direction is given if a line contains fewer than three characters. That may be something to consider.
lines = File.open("textfile.txt").read.split("\n") hsh = {} lines.each do |line| next if line == "" hsh[line[0..2]] = line[3..-1] end using your method of slowly nibbling at the file f = File.open("textfile.txt") hsh = {} loop do x = f.gets break unless x hsh[x[0..2]] = x[3..-1] end
Borrowing #Cary's sample file... text = <<_ Now is the time for all good Rubiests to come to the aid of their bowling team. _ FName = 'temp' File.write(FName, text) Now the file exists. Convert it to a 2 dimensional array. This array is trivially converted to a hash File.foreach(FName).map{|x| [x.slice!(0,3), x]}.to_h => {"Now"=>" is the\n", "tim"=>"e for all\n", "goo"=>"d Rubiests\n", "to "=>"come to the\n", "aid"=>" of their\n", "bow"=>"ling team.\n"}
Here you go : Sample data: [zatcsv]$ cat foo.txt TOK UPDATE DATE SHOT TIME AUXHEAT PHASE STATE PGASA PGASZ BGASA BGASZ BGASA2 BGASZ2 PIMPA PIMPZ PELLET RGEO RMAG AMIN SEPLIM XPLIM KAPPA DELTA INDENT AREA VOL CONFIG IGRADB WALMAT DIVMAT LIMMAT EVAP BT IP VSURF Q95 BEPMHD BETMHD BEPDIA NEL DNELDT ZEFF PRAD POHM ENBI PINJ BSOURCE PINJ2 BSOURCE2 COCTR PNBI ECHFREQ ECHMODE ECHLOC PECH ICFREQ ICSCHEME ICANTEN PICRH LHFREQ LHNPAR PLH IBWFREQ PIBW TE0 TI0 WFANI WFICRH MEFF ISEQ WTH WTOT JET 20031201 20001006 53521 1.000E+01 NBIC HSELM TRANS 2.000E+00 1.000E+00 2 1 0 0 1.658E+01 8.152E+00 NONE 2.888E+00 HEEH OIJ OIJJ 3.047E+00 9.807E-01 2.924E-02 7.304E-02 1.572E+00 1.781E-01 0.000E+00 4.572E+00 8.161E+01 LSN 1 IN/ 2.000E+06 1.013E-01 6.001E+00 1.053E+00 9.252E-01 1.128E+00 3.106E+19 3.106E+19 6.612E+00 4.515E+06 5.122E+04 1.000E+05 1.466E+07 771706 0.000E+00 652114 1.000E+00 1.420E+07 -9.999E-09 NONE NONE 0.000E+00 5.100E+07 HMIN MONOPOLE 4.027E+06 3.700E+09 1.840E+00 2.000E+06 -9.999E-09 0.000E+00 9.295E+03 1.373E+04 6.913E-01 7.319E+05 2.000E+00 NONE 3.715E+06 5.381E+06 1.282E+06 1.297E+07 1.210E+07 something like this will do it for you : [za csv]$cat text_to_hash.rb #!/usr/bin/env ruby file_dir = "/dir/to_folder/foo.txt" thehash = Hash.new line = File.read(file_dir).each_line do |line| thehash[ key = line.slice(0..2)] = val = line.slice(3..-1) thehash.each { |k , val| puts " Key: #{key} Value: #{val}"} end Outputs: [za csv]$ ./text_to_hash.rb Key: TOK Value: UPDATE DATE SHOT TIME AUXHEAT PHASE STATE PGASA PGASZ BGASA BGASZ BGASA2 BGASZ2 PIMPA Key: PIM Value: PZ PELLET RGEO RMAG AMIN SEPLIM XPLIM KAPPA DELTA INDENT AREA VOL CONFIG IGRADB WALMAT DIVMAT LIMMAT EVAP Key: ECH Value: MODE ECHLOC PECH ICFREQ ICSCHEME ICANTEN PICRH LHFREQ LHNPAR PLH IBWFREQ PIBW TE0 TI0 WFANI WFICRH MEFF ISEQ WTH WTOT Key: JET Value: 20031201 20001006 53521 1.000E+01 NBIC HSELM TRANS 2.000E+00 1.000E+00 2 1 0 0 1.658E+01 8.152E+00 NONE 2.888E+00 Key: HEE Value: H OIJ OIJJ 3.047E+00 9.807E-01 2.924E-02 7.304E-02 1.572E+00 1.781E-01 0.000E+00 4.572E+00 8.161E+01 LSN 1 IN/ Key: 2.0 Value: 00E+06 1.013E-01 6.001E+00 1.053E+00 9.252E-01 1.128E+00 3.106E+19 3.106E+19 6.612E+00 4.515E+06 5.122E+04 1.000E+05 1.466E+07 Key: 771 Value: 706 0.000E+00 652114 1.000E+00 1.420E+07 -9.999E-09 NONE NONE 0.000E+00 5.100E+07 HMIN MONOPOLE 4.027E+06 3.700E+09 1.840E+00 Key: 2.0 Value: 00E+06 -9.999E-09 0.000E+00 9.295E+03 1.373E+04 6.913E-01 7.319E+05 2.000E+00 NONE 3.715E+06 5.381E+06 1.282E+06 1.297E+07 1.210E+07 Key: 4.4 Value: 45E-01 2.194E-01
Ruby - How to subtract numbers of two files and save the result in one of them on a specified position?
I have 2 txt files with different strings and numbers in them splitted with ; Now I need to subtract the ((number on position 2 in file1) - (number on position 25 in file2)) = result Now I want to replace the (number on position 2 in file1) with the result. I tried my code below but it only appends the number in the end of the file and its not the result of the calculation which got appended. def calc f1 = File.open("./file1.txt", File::RDWR) f2 = File.open("./file2.txt", File::RDWR) f1.flock(File::LOCK_EX) f2.flock(File::LOCK_EX) f1.each.zip(f2.each).each do |line, line2| bg = line.split(";").compact.collect(&:strip) bd = line2.split(";").compact.collect(&:strip) n = bd[2].to_i - bg[25].to_i f2.print bd[2] << n #puts "#{n}" Only for testing end f1.flock(File::LOCK_UN) f2.flock(File::LOCK_UN) f1.close && f2.close end
Use something like this: lines1 = File.readlines('file1.txt').map(&:to_i) lines2 = File.readlines('file2.txt').map(&:to_i) result = lines1.zip(lines2).map do |value1, value2| value1 - value2 } File.write('file1.txt', result.join(?\n)) This code load all files in memory, then calculate result and write it to first file. FYI: If you want to use your code just save result to other file (i.e. result.txt) and at the end copy it to original file.
Positional Argument Undefined
I am working on a larger project to write a code so the user can play Connect 4 against the computer. Right now, the user can choose whether or not to go first and the board is drawn. While truing to make sure that the user can only enter legal moves, I have run into a problem where my function legal_moves() takes 1 positional argument, and 0 are given, but I do not understand what I need to do to male everything agree. #connect 4 #using my own formating import random #define global variables X = "X" O = "O" EMPTY = "_" TIE = "TIE" NUM_ROWS = 6 NUM_COLS = 8 def display_instruct(): """Display game instructions.""" print( """ Welcome to the second greatest intellectual challenge of all time: Connect4. This will be a showdown between your human brain and my silicon processor. You will make your move known by entering a column number, 1 - 7. Your move (if that column isn't already filled) will move to the lowest available position. Prepare yourself, human. May the Schwartz be with you! \n """ ) def ask_yes_no(question): """Ask a yes or no question.""" response = None while response not in ("y", "n"): response = input(question).lower() return response def ask_number(question,low,high): """Ask for a number within range.""" #using range in Python sense-i.e., to ask for #a number between 1 and 7, call ask_number with low=1, high=8 low=1 high=NUM_COLS response = None while response not in range (low,high): response=int(input(question)) return response def pieces(): """Determine if player or computer goes first.""" go_first = ask_yes_no("Do you require the first move? (y/n): ") if go_first == "y": print("\nThen take the first move. You will need it.") human = X computer = O else: print("\nYour bravery will be your undoing... I will go first.") computer = X human = O return computer, human def new_board(): board = [] for x in range (NUM_COLS): board.append([" "]*NUM_ROWS) return board def display_board(board): """Display game board on screen.""" for r in range(NUM_ROWS): print_row(board,r) print("\n") def print_row(board, num): """Print specified row from current board""" this_row = board[num] print("\n\t| ", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num], "|", this_row[num],"|") print("\t", "|---|---|---|---|---|---|---|") # everything works up to here! def legal_moves(board): """Create list of column numbers where a player can drop piece""" legals = [] if move < NUM_COLS: # make sure this is a legal column for r in range(NUM_ROWS): legals.append(board[move]) return legals #returns a list of legal columns #in human_move function, move input must be in legal_moves list print (legals) def human_move(board,human): """Get human move""" legals = legal_moves(board) print("LEGALS:", legals) move = None while move not in legals: move = ask_number("Which column will you move to? (1-7):", 1, NUM_COLS) if move not in legals: print("\nThat column is already full, nerdling. Choose another.\n") print("Human moving to column", move) return move #return the column number chosen by user def get_move_row(turn,move): move=ask_number("Which column would you like to drop a piece?") for m in range (NUM_COLS): place_piece(turn,move) display_board() def place_piece(turn,move): if this_row[m[move]]==" ": this_row.append[m[move]]=turn display_instruct() computer,human=pieces() board=new_board() display_board(board) move= int(input("Move?")) legal_moves() print ("Human:", human, "\nComputer:", computer)
Right down the bottom of the script, you call: move= int(input("Move?")) legal_moves() # ^ no arguments This does not supply the necessary board argument, hence the error message.
Radix sort not working in Lua
Firstly I should mention I've not been coding very long at all, although that much is probably obvious from my code :P I'm having two problems, firstly the sort isn't functioning correctly but does sort the numbers by their length. Any help here would be appreciated. Secondly it's changing both the table it grabs and the table it returns (not sure why). How do I prevent it changing the table it grabs? I'd prefer if people didn't post a fully optisimised premade code as I'm not going to learn or understand anything that way. function radix_sort(x) pass, bucket, maxstring = 0, x, 2 while true do pass = pass + 1 queue = {} for n=#bucket,1,-1 do key_length = string.len(bucket[n]) key = bucket[n] if pass == 1 and key_length > maxstring then maxstring = key_length end if key_length == pass then pool = string.sub(key, 1,1) if queue[pool + 1] == nil then queue[pool + 1] = {} end table.insert(queue[pool + 1], key) table.remove(bucket, n) end end for k,v in pairs(queue) do for n=1,#v do table.insert(bucket, v[n]) end end if pass == maxstring then break end end return bucket end
There's a lot of changes I made to get this working, so hopefully you can look through and pickup on them. I tried to comment as best I could. function radix_sort(x) pass, maxstring = 0, 0 -- to avoid overwriting x, copy into bucket like this -- it also gives the chance to init maxstring bucket={} for n=1,#x,1 do -- since we can, convert all entries to strings for string functions below bucket[n]=tostring(x[n]) key_length = string.len(bucket[n]) if key_length > maxstring then maxstring = key_length end end -- not a fan of "while true ... break" when we can set a condition here while pass <= maxstring do pass = pass + 1 -- init both queue and all queue entries so ipairs doesn't skip anything below queue = {} for n=1,10,1 do queue[n] = {} end -- go through bucket entries in order for an LSD radix sort for n=1,#bucket,1 do key_length = string.len(bucket[n]) key = bucket[n] -- for string.sub, start at end of string (LSD sort) with -pass if key_length >= pass then pool = tonumber(string.sub(key, pass*-1, pass*-1)) else pool = 0 end -- add to appropriate queue, but no need to remove from bucket, reset it below table.insert(queue[pool + 1], key) end -- empty out the bucket and reset, use ipairs to call queues in order bucket={} for k,v in ipairs(queue) do for n=1,#v do table.insert(bucket, v[n]) end end end return bucket end Here's a test run: > input={55,2,123,1,42,9999,6,666,999,543,13} > output=radix_sort(input) > for k,v in pairs(output) do > print (k , " = " , v) > end 1 = 1 2 = 2 3 = 6 4 = 13 5 = 42 6 = 55 7 = 123 8 = 543 9 = 666 10 = 999 11 = 9999
pool = string.sub(key, 1,1) always looks at the first character; perhaps you meant string.sub(key, pass, 1)